Coverage

20%
32161
6467
25694

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/lib/database.js

92%
13
12
1
LineHitsSource
11'use strict';
21var mongoose = require('mongoose'),
3connectionString;
4
51module.exports.config = function (nconf) {
61 console.log('***');
7 // 27017 is mandatory to socket.io-mongo to avoid localhost:Nan error on startup
81 connectionString = 'mongodb://localhost:27017/innovatio';
91 mongoose.connect(connectionString);
101 var db = mongoose.connection;
11
12 // set dynamix databse connection to store conf for resuse in connect-mongo session store
131 nconf.set('middleware:session:config:mongoose_connection',db);
14
15
161 db.on('error', console.error.bind(console, 'connection error:'));
171 db.once('open', function callback() {
180 console.log('db connection open');
19 });
20};
21
221module.exports.connectionString = function(){
231 return connectionString;
24};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/baucis/node_modules/async/lib/async.js

16%
535
87
448
LineHitsSource
1/*global setImmediate: false, setTimeout: false, console: false */
21(function () {
3
41 var async = {};
5
6 // global on the server, window in the browser
71 var root, previous_async;
8
91 root = this;
101 if (root != null) {
111 previous_async = root.async;
12 }
13
141 async.noConflict = function () {
150 root.async = previous_async;
160 return async;
17 };
18
191 function only_once(fn) {
200 var called = false;
210 return function() {
220 if (called) throw new Error("Callback was already called.");
230 called = true;
240 fn.apply(root, arguments);
25 }
26 }
27
28 //// cross-browser compatiblity functions ////
29
301 var _each = function (arr, iterator) {
310 if (arr.forEach) {
320 return arr.forEach(iterator);
33 }
340 for (var i = 0; i < arr.length; i += 1) {
350 iterator(arr[i], i, arr);
36 }
37 };
38
391 var _map = function (arr, iterator) {
400 if (arr.map) {
410 return arr.map(iterator);
42 }
430 var results = [];
440 _each(arr, function (x, i, a) {
450 results.push(iterator(x, i, a));
46 });
470 return results;
48 };
49
501 var _reduce = function (arr, iterator, memo) {
510 if (arr.reduce) {
520 return arr.reduce(iterator, memo);
53 }
540 _each(arr, function (x, i, a) {
550 memo = iterator(memo, x, i, a);
56 });
570 return memo;
58 };
59
601 var _keys = function (obj) {
610 if (Object.keys) {
620 return Object.keys(obj);
63 }
640 var keys = [];
650 for (var k in obj) {
660 if (obj.hasOwnProperty(k)) {
670 keys.push(k);
68 }
69 }
700 return keys;
71 };
72
73 //// exported async module functions ////
74
75 //// nextTick implementation with browser-compatible fallback ////
761 if (typeof process === 'undefined' || !(process.nextTick)) {
770 if (typeof setImmediate === 'function') {
780 async.nextTick = function (fn) {
79 // not a direct alias for IE10 compatibility
800 setImmediate(fn);
81 };
820 async.setImmediate = async.nextTick;
83 }
84 else {
850 async.nextTick = function (fn) {
860 setTimeout(fn, 0);
87 };
880 async.setImmediate = async.nextTick;
89 }
90 }
91 else {
921 async.nextTick = process.nextTick;
931 if (typeof setImmediate !== 'undefined') {
941 async.setImmediate = function (fn) {
95 // not a direct alias for IE10 compatibility
960 setImmediate(fn);
97 };
98 }
99 else {
1000 async.setImmediate = async.nextTick;
101 }
102 }
103
1041 async.each = function (arr, iterator, callback) {
1050 callback = callback || function () {};
1060 if (!arr.length) {
1070 return callback();
108 }
1090 var completed = 0;
1100 _each(arr, function (x) {
1110 iterator(x, only_once(function (err) {
1120 if (err) {
1130 callback(err);
1140 callback = function () {};
115 }
116 else {
1170 completed += 1;
1180 if (completed >= arr.length) {
1190 callback(null);
120 }
121 }
122 }));
123 });
124 };
1251 async.forEach = async.each;
126
1271 async.eachSeries = function (arr, iterator, callback) {
1280 callback = callback || function () {};
1290 if (!arr.length) {
1300 return callback();
131 }
1320 var completed = 0;
1330 var iterate = function () {
1340 iterator(arr[completed], function (err) {
1350 if (err) {
1360 callback(err);
1370 callback = function () {};
138 }
139 else {
1400 completed += 1;
1410 if (completed >= arr.length) {
1420 callback(null);
143 }
144 else {
1450 iterate();
146 }
147 }
148 });
149 };
1500 iterate();
151 };
1521 async.forEachSeries = async.eachSeries;
153
1541 async.eachLimit = function (arr, limit, iterator, callback) {
1550 var fn = _eachLimit(limit);
1560 fn.apply(null, [arr, iterator, callback]);
157 };
1581 async.forEachLimit = async.eachLimit;
159
1601 var _eachLimit = function (limit) {
161
1620 return function (arr, iterator, callback) {
1630 callback = callback || function () {};
1640 if (!arr.length || limit <= 0) {
1650 return callback();
166 }
1670 var completed = 0;
1680 var started = 0;
1690 var running = 0;
170
1710 (function replenish () {
1720 if (completed >= arr.length) {
1730 return callback();
174 }
175
1760 while (running < limit && started < arr.length) {
1770 started += 1;
1780 running += 1;
1790 iterator(arr[started - 1], function (err) {
1800 if (err) {
1810 callback(err);
1820 callback = function () {};
183 }
184 else {
1850 completed += 1;
1860 running -= 1;
1870 if (completed >= arr.length) {
1880 callback();
189 }
190 else {
1910 replenish();
192 }
193 }
194 });
195 }
196 })();
197 };
198 };
199
200
2011 var doParallel = function (fn) {
2026 return function () {
2030 var args = Array.prototype.slice.call(arguments);
2040 return fn.apply(null, [async.each].concat(args));
205 };
206 };
2071 var doParallelLimit = function(limit, fn) {
2080 return function () {
2090 var args = Array.prototype.slice.call(arguments);
2100 return fn.apply(null, [_eachLimit(limit)].concat(args));
211 };
212 };
2131 var doSeries = function (fn) {
2146 return function () {
2150 var args = Array.prototype.slice.call(arguments);
2160 return fn.apply(null, [async.eachSeries].concat(args));
217 };
218 };
219
220
2211 var _asyncMap = function (eachfn, arr, iterator, callback) {
2220 var results = [];
2230 arr = _map(arr, function (x, i) {
2240 return {index: i, value: x};
225 });
2260 eachfn(arr, function (x, callback) {
2270 iterator(x.value, function (err, v) {
2280 results[x.index] = v;
2290 callback(err);
230 });
231 }, function (err) {
2320 callback(err, results);
233 });
234 };
2351 async.map = doParallel(_asyncMap);
2361 async.mapSeries = doSeries(_asyncMap);
2371 async.mapLimit = function (arr, limit, iterator, callback) {
2380 return _mapLimit(limit)(arr, iterator, callback);
239 };
240
2411 var _mapLimit = function(limit) {
2420 return doParallelLimit(limit, _asyncMap);
243 };
244
245 // reduce only has a series version, as doing reduce in parallel won't
246 // work in many situations.
2471 async.reduce = function (arr, memo, iterator, callback) {
2480 async.eachSeries(arr, function (x, callback) {
2490 iterator(memo, x, function (err, v) {
2500 memo = v;
2510 callback(err);
252 });
253 }, function (err) {
2540 callback(err, memo);
255 });
256 };
257 // inject alias
2581 async.inject = async.reduce;
259 // foldl alias
2601 async.foldl = async.reduce;
261
2621 async.reduceRight = function (arr, memo, iterator, callback) {
2630 var reversed = _map(arr, function (x) {
2640 return x;
265 }).reverse();
2660 async.reduce(reversed, memo, iterator, callback);
267 };
268 // foldr alias
2691 async.foldr = async.reduceRight;
270
2711 var _filter = function (eachfn, arr, iterator, callback) {
2720 var results = [];
2730 arr = _map(arr, function (x, i) {
2740 return {index: i, value: x};
275 });
2760 eachfn(arr, function (x, callback) {
2770 iterator(x.value, function (v) {
2780 if (v) {
2790 results.push(x);
280 }
2810 callback();
282 });
283 }, function (err) {
2840 callback(_map(results.sort(function (a, b) {
2850 return a.index - b.index;
286 }), function (x) {
2870 return x.value;
288 }));
289 });
290 };
2911 async.filter = doParallel(_filter);
2921 async.filterSeries = doSeries(_filter);
293 // select alias
2941 async.select = async.filter;
2951 async.selectSeries = async.filterSeries;
296
2971 var _reject = function (eachfn, arr, iterator, callback) {
2980 var results = [];
2990 arr = _map(arr, function (x, i) {
3000 return {index: i, value: x};
301 });
3020 eachfn(arr, function (x, callback) {
3030 iterator(x.value, function (v) {
3040 if (!v) {
3050 results.push(x);
306 }
3070 callback();
308 });
309 }, function (err) {
3100 callback(_map(results.sort(function (a, b) {
3110 return a.index - b.index;
312 }), function (x) {
3130 return x.value;
314 }));
315 });
316 };
3171 async.reject = doParallel(_reject);
3181 async.rejectSeries = doSeries(_reject);
319
3201 var _detect = function (eachfn, arr, iterator, main_callback) {
3210 eachfn(arr, function (x, callback) {
3220 iterator(x, function (result) {
3230 if (result) {
3240 main_callback(x);
3250 main_callback = function () {};
326 }
327 else {
3280 callback();
329 }
330 });
331 }, function (err) {
3320 main_callback();
333 });
334 };
3351 async.detect = doParallel(_detect);
3361 async.detectSeries = doSeries(_detect);
337
3381 async.some = function (arr, iterator, main_callback) {
3390 async.each(arr, function (x, callback) {
3400 iterator(x, function (v) {
3410 if (v) {
3420 main_callback(true);
3430 main_callback = function () {};
344 }
3450 callback();
346 });
347 }, function (err) {
3480 main_callback(false);
349 });
350 };
351 // any alias
3521 async.any = async.some;
353
3541 async.every = function (arr, iterator, main_callback) {
3550 async.each(arr, function (x, callback) {
3560 iterator(x, function (v) {
3570 if (!v) {
3580 main_callback(false);
3590 main_callback = function () {};
360 }
3610 callback();
362 });
363 }, function (err) {
3640 main_callback(true);
365 });
366 };
367 // all alias
3681 async.all = async.every;
369
3701 async.sortBy = function (arr, iterator, callback) {
3710 async.map(arr, function (x, callback) {
3720 iterator(x, function (err, criteria) {
3730 if (err) {
3740 callback(err);
375 }
376 else {
3770 callback(null, {value: x, criteria: criteria});
378 }
379 });
380 }, function (err, results) {
3810 if (err) {
3820 return callback(err);
383 }
384 else {
3850 var fn = function (left, right) {
3860 var a = left.criteria, b = right.criteria;
3870 return a < b ? -1 : a > b ? 1 : 0;
388 };
3890 callback(null, _map(results.sort(fn), function (x) {
3900 return x.value;
391 }));
392 }
393 });
394 };
395
3961 async.auto = function (tasks, callback) {
3970 callback = callback || function () {};
3980 var keys = _keys(tasks);
3990 if (!keys.length) {
4000 return callback(null);
401 }
402
4030 var results = {};
404
4050 var listeners = [];
4060 var addListener = function (fn) {
4070 listeners.unshift(fn);
408 };
4090 var removeListener = function (fn) {
4100 for (var i = 0; i < listeners.length; i += 1) {
4110 if (listeners[i] === fn) {
4120 listeners.splice(i, 1);
4130 return;
414 }
415 }
416 };
4170 var taskComplete = function () {
4180 _each(listeners.slice(0), function (fn) {
4190 fn();
420 });
421 };
422
4230 addListener(function () {
4240 if (_keys(results).length === keys.length) {
4250 callback(null, results);
4260 callback = function () {};
427 }
428 });
429
4300 _each(keys, function (k) {
4310 var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
4320 var taskCallback = function (err) {
4330 var args = Array.prototype.slice.call(arguments, 1);
4340 if (args.length <= 1) {
4350 args = args[0];
436 }
4370 if (err) {
4380 var safeResults = {};
4390 _each(_keys(results), function(rkey) {
4400 safeResults[rkey] = results[rkey];
441 });
4420 safeResults[k] = args;
4430 callback(err, safeResults);
444 // stop subsequent errors hitting callback multiple times
4450 callback = function () {};
446 }
447 else {
4480 results[k] = args;
4490 async.setImmediate(taskComplete);
450 }
451 };
4520 var requires = task.slice(0, Math.abs(task.length - 1)) || [];
4530 var ready = function () {
4540 return _reduce(requires, function (a, x) {
4550 return (a && results.hasOwnProperty(x));
456 }, true) && !results.hasOwnProperty(k);
457 };
4580 if (ready()) {
4590 task[task.length - 1](taskCallback, results);
460 }
461 else {
4620 var listener = function () {
4630 if (ready()) {
4640 removeListener(listener);
4650 task[task.length - 1](taskCallback, results);
466 }
467 };
4680 addListener(listener);
469 }
470 });
471 };
472
4731 async.waterfall = function (tasks, callback) {
4740 callback = callback || function () {};
4750 if (tasks.constructor !== Array) {
4760 var err = new Error('First argument to waterfall must be an array of functions');
4770 return callback(err);
478 }
4790 if (!tasks.length) {
4800 return callback();
481 }
4820 var wrapIterator = function (iterator) {
4830 return function (err) {
4840 if (err) {
4850 callback.apply(null, arguments);
4860 callback = function () {};
487 }
488 else {
4890 var args = Array.prototype.slice.call(arguments, 1);
4900 var next = iterator.next();
4910 if (next) {
4920 args.push(wrapIterator(next));
493 }
494 else {
4950 args.push(callback);
496 }
4970 async.setImmediate(function () {
4980 iterator.apply(null, args);
499 });
500 }
501 };
502 };
5030 wrapIterator(async.iterator(tasks))();
504 };
505
5061 var _parallel = function(eachfn, tasks, callback) {
5070 callback = callback || function () {};
5080 if (tasks.constructor === Array) {
5090 eachfn.map(tasks, function (fn, callback) {
5100 if (fn) {
5110 fn(function (err) {
5120 var args = Array.prototype.slice.call(arguments, 1);
5130 if (args.length <= 1) {
5140 args = args[0];
515 }
5160 callback.call(null, err, args);
517 });
518 }
519 }, callback);
520 }
521 else {
5220 var results = {};
5230 eachfn.each(_keys(tasks), function (k, callback) {
5240 tasks[k](function (err) {
5250 var args = Array.prototype.slice.call(arguments, 1);
5260 if (args.length <= 1) {
5270 args = args[0];
528 }
5290 results[k] = args;
5300 callback(err);
531 });
532 }, function (err) {
5330 callback(err, results);
534 });
535 }
536 };
537
5381 async.parallel = function (tasks, callback) {
5390 _parallel({ map: async.map, each: async.each }, tasks, callback);
540 };
541
5421 async.parallelLimit = function(tasks, limit, callback) {
5430 _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
544 };
545
5461 async.series = function (tasks, callback) {
5470 callback = callback || function () {};
5480 if (tasks.constructor === Array) {
5490 async.mapSeries(tasks, function (fn, callback) {
5500 if (fn) {
5510 fn(function (err) {
5520 var args = Array.prototype.slice.call(arguments, 1);
5530 if (args.length <= 1) {
5540 args = args[0];
555 }
5560 callback.call(null, err, args);
557 });
558 }
559 }, callback);
560 }
561 else {
5620 var results = {};
5630 async.eachSeries(_keys(tasks), function (k, callback) {
5640 tasks[k](function (err) {
5650 var args = Array.prototype.slice.call(arguments, 1);
5660 if (args.length <= 1) {
5670 args = args[0];
568 }
5690 results[k] = args;
5700 callback(err);
571 });
572 }, function (err) {
5730 callback(err, results);
574 });
575 }
576 };
577
5781 async.iterator = function (tasks) {
5790 var makeCallback = function (index) {
5800 var fn = function () {
5810 if (tasks.length) {
5820 tasks[index].apply(null, arguments);
583 }
5840 return fn.next();
585 };
5860 fn.next = function () {
5870 return (index < tasks.length - 1) ? makeCallback(index + 1): null;
588 };
5890 return fn;
590 };
5910 return makeCallback(0);
592 };
593
5941 async.apply = function (fn) {
5950 var args = Array.prototype.slice.call(arguments, 1);
5960 return function () {
5970 return fn.apply(
598 null, args.concat(Array.prototype.slice.call(arguments))
599 );
600 };
601 };
602
6031 var _concat = function (eachfn, arr, fn, callback) {
6040 var r = [];
6050 eachfn(arr, function (x, cb) {
6060 fn(x, function (err, y) {
6070 r = r.concat(y || []);
6080 cb(err);
609 });
610 }, function (err) {
6110 callback(err, r);
612 });
613 };
6141 async.concat = doParallel(_concat);
6151 async.concatSeries = doSeries(_concat);
616
6171 async.whilst = function (test, iterator, callback) {
6180 if (test()) {
6190 iterator(function (err) {
6200 if (err) {
6210 return callback(err);
622 }
6230 async.whilst(test, iterator, callback);
624 });
625 }
626 else {
6270 callback();
628 }
629 };
630
6311 async.doWhilst = function (iterator, test, callback) {
6320 iterator(function (err) {
6330 if (err) {
6340 return callback(err);
635 }
6360 if (test()) {
6370 async.doWhilst(iterator, test, callback);
638 }
639 else {
6400 callback();
641 }
642 });
643 };
644
6451 async.until = function (test, iterator, callback) {
6460 if (!test()) {
6470 iterator(function (err) {
6480 if (err) {
6490 return callback(err);
650 }
6510 async.until(test, iterator, callback);
652 });
653 }
654 else {
6550 callback();
656 }
657 };
658
6591 async.doUntil = function (iterator, test, callback) {
6600 iterator(function (err) {
6610 if (err) {
6620 return callback(err);
663 }
6640 if (!test()) {
6650 async.doUntil(iterator, test, callback);
666 }
667 else {
6680 callback();
669 }
670 });
671 };
672
6731 async.queue = function (worker, concurrency) {
6740 if (concurrency === undefined) {
6750 concurrency = 1;
676 }
6770 function _insert(q, data, pos, callback) {
6780 if(data.constructor !== Array) {
6790 data = [data];
680 }
6810 _each(data, function(task) {
6820 var item = {
683 data: task,
684 callback: typeof callback === 'function' ? callback : null
685 };
686
6870 if (pos) {
6880 q.tasks.unshift(item);
689 } else {
6900 q.tasks.push(item);
691 }
692
6930 if (q.saturated && q.tasks.length === concurrency) {
6940 q.saturated();
695 }
6960 async.setImmediate(q.process);
697 });
698 }
699
7000 var workers = 0;
7010 var q = {
702 tasks: [],
703 concurrency: concurrency,
704 saturated: null,
705 empty: null,
706 drain: null,
707 push: function (data, callback) {
7080 _insert(q, data, false, callback);
709 },
710 unshift: function (data, callback) {
7110 _insert(q, data, true, callback);
712 },
713 process: function () {
7140 if (workers < q.concurrency && q.tasks.length) {
7150 var task = q.tasks.shift();
7160 if (q.empty && q.tasks.length === 0) {
7170 q.empty();
718 }
7190 workers += 1;
7200 var next = function () {
7210 workers -= 1;
7220 if (task.callback) {
7230 task.callback.apply(task, arguments);
724 }
7250 if (q.drain && q.tasks.length + workers === 0) {
7260 q.drain();
727 }
7280 q.process();
729 };
7300 var cb = only_once(next);
7310 worker(task.data, cb);
732 }
733 },
734 length: function () {
7350 return q.tasks.length;
736 },
737 running: function () {
7380 return workers;
739 }
740 };
7410 return q;
742 };
743
7441 async.cargo = function (worker, payload) {
7450 var working = false,
746 tasks = [];
747
7480 var cargo = {
749 tasks: tasks,
750 payload: payload,
751 saturated: null,
752 empty: null,
753 drain: null,
754 push: function (data, callback) {
7550 if(data.constructor !== Array) {
7560 data = [data];
757 }
7580 _each(data, function(task) {
7590 tasks.push({
760 data: task,
761 callback: typeof callback === 'function' ? callback : null
762 });
7630 if (cargo.saturated && tasks.length === payload) {
7640 cargo.saturated();
765 }
766 });
7670 async.setImmediate(cargo.process);
768 },
769 process: function process() {
7700 if (working) return;
7710 if (tasks.length === 0) {
7720 if(cargo.drain) cargo.drain();
7730 return;
774 }
775
7760 var ts = typeof payload === 'number'
777 ? tasks.splice(0, payload)
778 : tasks.splice(0);
779
7800 var ds = _map(ts, function (task) {
7810 return task.data;
782 });
783
7840 if(cargo.empty) cargo.empty();
7850 working = true;
7860 worker(ds, function () {
7870 working = false;
788
7890 var args = arguments;
7900 _each(ts, function (data) {
7910 if (data.callback) {
7920 data.callback.apply(null, args);
793 }
794 });
795
7960 process();
797 });
798 },
799 length: function () {
8000 return tasks.length;
801 },
802 running: function () {
8030 return working;
804 }
805 };
8060 return cargo;
807 };
808
8091 var _console_fn = function (name) {
8102 return function (fn) {
8110 var args = Array.prototype.slice.call(arguments, 1);
8120 fn.apply(null, args.concat([function (err) {
8130 var args = Array.prototype.slice.call(arguments, 1);
8140 if (typeof console !== 'undefined') {
8150 if (err) {
8160 if (console.error) {
8170 console.error(err);
818 }
819 }
8200 else if (console[name]) {
8210 _each(args, function (x) {
8220 console[name](x);
823 });
824 }
825 }
826 }]));
827 };
828 };
8291 async.log = _console_fn('log');
8301 async.dir = _console_fn('dir');
831 /*async.info = _console_fn('info');
832 async.warn = _console_fn('warn');
833 async.error = _console_fn('error');*/
834
8351 async.memoize = function (fn, hasher) {
8360 var memo = {};
8370 var queues = {};
8380 hasher = hasher || function (x) {
8390 return x;
840 };
8410 var memoized = function () {
8420 var args = Array.prototype.slice.call(arguments);
8430 var callback = args.pop();
8440 var key = hasher.apply(null, args);
8450 if (key in memo) {
8460 callback.apply(null, memo[key]);
847 }
8480 else if (key in queues) {
8490 queues[key].push(callback);
850 }
851 else {
8520 queues[key] = [callback];
8530 fn.apply(null, args.concat([function () {
8540 memo[key] = arguments;
8550 var q = queues[key];
8560 delete queues[key];
8570 for (var i = 0, l = q.length; i < l; i++) {
8580 q[i].apply(null, arguments);
859 }
860 }]));
861 }
862 };
8630 memoized.memo = memo;
8640 memoized.unmemoized = fn;
8650 return memoized;
866 };
867
8681 async.unmemoize = function (fn) {
8690 return function () {
8700 return (fn.unmemoized || fn).apply(null, arguments);
871 };
872 };
873
8741 async.times = function (count, iterator, callback) {
8750 var counter = [];
8760 for (var i = 0; i < count; i++) {
8770 counter.push(i);
878 }
8790 return async.map(counter, iterator, callback);
880 };
881
8821 async.timesSeries = function (count, iterator, callback) {
8830 var counter = [];
8840 for (var i = 0; i < count; i++) {
8850 counter.push(i);
886 }
8870 return async.mapSeries(counter, iterator, callback);
888 };
889
8901 async.compose = function (/* functions... */) {
8910 var fns = Array.prototype.reverse.call(arguments);
8920 return function () {
8930 var that = this;
8940 var args = Array.prototype.slice.call(arguments);
8950 var callback = args.pop();
8960 async.reduce(fns, args, function (newargs, fn, cb) {
8970 fn.apply(that, newargs.concat([function () {
8980 var err = arguments[0];
8990 var nextargs = Array.prototype.slice.call(arguments, 1);
9000 cb(err, nextargs);
901 }]))
902 },
903 function (err, results) {
9040 callback.apply(that, [err].concat(results));
905 });
906 };
907 };
908
9091 var _applyEach = function (eachfn, fns /*args...*/) {
9100 var go = function () {
9110 var that = this;
9120 var args = Array.prototype.slice.call(arguments);
9130 var callback = args.pop();
9140 return eachfn(fns, function (fn, cb) {
9150 fn.apply(that, args.concat([cb]));
916 },
917 callback);
918 };
9190 if (arguments.length > 2) {
9200 var args = Array.prototype.slice.call(arguments, 2);
9210 return go.apply(this, args);
922 }
923 else {
9240 return go;
925 }
926 };
9271 async.applyEach = doParallel(_applyEach);
9281 async.applyEachSeries = doSeries(_applyEach);
929
9301 async.forever = function (fn, callback) {
9310 function next(err) {
9320 if (err) {
9330 if (callback) {
9340 return callback(err);
935 }
9360 throw err;
937 }
9380 fn(next);
939 }
9400 next();
941 };
942
943 // AMD / RequireJS
9441 if (typeof define !== 'undefined' && define.amd) {
9450 define([], function () {
9460 return async;
947 });
948 }
949 // Node.js
9501 else if (typeof module !== 'undefined' && module.exports) {
9511 module.exports = async;
952 }
953 // included directly via <script> tag
954 else {
9550 root.async = async;
956 }
957
958}());
959

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/baucis/node_modules/lingo/lib/inflection.js

58%
41
24
17
LineHitsSource
1
2/*!
3 * Lingo - inflection
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Language = require('./language');
13
14/**
15 * Check if a `word` is uncountable.
16 *
17 * @param {String} word
18 * @return {Boolean}
19 * @api public
20 */
21
221Language.prototype.isUncountable = function(word){
230 return !!this.rules.uncountable[word];
24};
25
26/**
27 * Add an uncountable `word`.
28 *
29 * @param {String} word
30 * @return {Language} for chaining
31 * @api public
32 */
33
341Language.prototype.uncountable = function(word){
3544 this.rules.uncountable[word] = word;
3644 return this;
37};
38
39/**
40 * Add an irreglar `singular` / `plural` map.
41 *
42 * @param {String} singular
43 * @param {String} plural
44 * @return {Language} for chaining
45 * @api public
46 */
47
481Language.prototype.irregular = function(singular, plural){
4931 this.rules.irregular.plural[singular] = plural;
5031 this.rules.irregular.singular[plural] = singular;
5131 return this;
52};
53
54/**
55 * Add a pluralization `rule` for numbers
56 *
57 * @param {RegExp} rule
58 * @return {Language} for chaining
59 * @api public
60 */
61
621Language.prototype.pluralNumbers = function(rule){
632 this.rules.pluralNumbers = rule;
642 return this;
65};
66
67/**
68 * Add a pluralization `rule` with the given `substitution`.
69 *
70 * @param {RegExp} rule
71 * @param {String} substitution
72 * @return {Language} for chaining
73 * @api public
74 */
75
761Language.prototype.plural = function(rule, substitution){
7731 this.rules.plural.unshift([rule, substitution]);
7831 return this;
79};
80
81/**
82 * Add a singularization `rule` with the given `substitution`.
83 *
84 * @param {RegExp} rule
85 * @param {String} substitution
86 * @return {Language} for chaining
87 * @api public
88 */
89
901Language.prototype.singular = function(rule, substitution){
9137 this.rules.singular.unshift([rule, substitution]);
9237 return this;
93};
94
95/**
96 * Pluralize the given `word`.
97 *
98 * @param {String} word
99 * @return {String}
100 * @api public
101 */
102
1031Language.prototype.pluralize = function(word){
1040 return this.inflect(word, 'plural');
105};
106
107/**
108 * Check if `word` is plural.
109 *
110 * @param {String or Number} word
111 * @return {Boolean}
112 * @api public
113 */
114
1151Language.prototype.isPlural = function (word) {
1160 if ('number' == typeof word) {
1170 return (this.rules.pluralNumbers || /.*/).test(word);
118 } else {
1190 return word == this.pluralize(this.singularize(word));
120 }
121};
122
123/**
124 * Singularize the given `word`.
125 *
126 * @param {String} word
127 * @return {String}
128 * @api public
129 */
130
1311Language.prototype.singularize = function (word) {
1320 return this.inflect(word, 'singular');
133};
134
135/**
136 * Check if `word` is singular.
137 *
138 * @param {String or Number} word
139 * @return {Boolean}
140 * @api public
141 */
142
1431Language.prototype.isSingular = function (word) {
1440 return !this.isPlural(word);
145};
146
147
148/**
149 * Tableize the given `str`.
150 *
151 * Examples:
152 *
153 * lingo.tableize('UserAccount');
154 * // => "user_accounts"
155 *
156 * lingo.tableize('User');
157 * // => "users"
158 *
159 * @param {String} str
160 * @return {String}
161 * @api public
162 */
163
1641exports.tableize = function(str){
1650 var underscored = exports.underscore(word);
1660 return Language.pluralize(underscored);
167};
168
169/**
170 * Perform `type` inflection rules on the given `word`.
171 *
172 * @param {String} word
173 * @param {String} type
174 * @return {String}
175 * @api private
176 */
177
1781Language.prototype.inflect = function(word, type) {
1790 if (this.isUncountable(word)) return word;
180
1810 var irregular = this.rules.irregular[type][word];
1820 if (irregular) return irregular;
183
1840 for (var i = 0, len = this.rules[type].length; i < len; ++i) {
1850 var rule = this.rules[type][i]
186 , regexp = rule[0]
187 , sub = rule[1];
1880 if (regexp.test(word)) {
1890 return word.replace(regexp, sub);
190 }
191 }
192
1930 return word;
194}
195

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/baucis/node_modules/lingo/lib/language.js

61%
13
8
5
LineHitsSource
1
2/*!
3 * Lingo - Language
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var lingo = require('./lingo');
13
14/**
15 * Initialize a new `Language` with the given `code` and `name`.
16 *
17 * @param {String} code
18 * @param {String} name
19 * @api public
20 */
21
221var Language = module.exports = function Language(code, name) {
232 this.code = code;
242 this.name = name;
252 this.translations = {};
262 this.rules = {
27 plural: []
28 , singular: []
29 , uncountable: {}
30 , irregular: { plural: {}, singular: {}}
31 };
322 lingo[code] = this;
33};
34
35/**
36 * Translate the given `str` with optional `params`.
37 *
38 * @param {String} str
39 * @param {Object} params
40 * @return {String}
41 * @api public
42 */
43
441Language.prototype.translate = function(str, params){
450 str = this.translations[str] || str;
460 if (params) {
470 str = str.replace(/\{([^}]+)\}/g, function(_, key){
480 return params[key];
49 });
50 }
510 return str;
52};
53

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/baucis/node_modules/lingo/lib/languages/en.js

100%
7
7
0
LineHitsSource
1/*!
2 * Lingo - languages - English
3 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
4 * MIT Licensed
5 */
6
7/**
8 * Module dependencies.
9 */
10
111var Language = require('../language');
12
13/**
14 * English.
15 */
16
171var en = module.exports = new Language('en', 'English');
18
19/**
20 * Number pluraluzation rule
21 */
221en.pluralNumbers(/[^1]/);
23
24/**
25 * Default pluralization rules.
26 */
27
281en.plural(/$/, "s")
29 .plural(/(s|ss|sh|ch|x|o)$/i, "$1es")
30 .plural(/y$/i, "ies")
31 .plural(/(o|e)y$/i, "$1ys")
32 .plural(/(octop|vir)us$/i, "$1i")
33 .plural(/(alias|status)$/i, "$1es")
34 .plural(/(bu)s$/i, "$1ses")
35 .plural(/([ti])um$/i, "$1a")
36 .plural(/sis$/i, "ses")
37 .plural(/(?:([^f])fe|([lr])f)$/i, "$1$2ves")
38 .plural(/([^aeiouy]|qu)y$/i, "$1ies")
39 .plural(/(matr|vert|ind)(?:ix|ex)$/i, "$1ices")
40 .plural(/([m|l])ouse$/i, "$1ice")
41 .plural(/^(ox)$/i, "$1en")
42 .plural(/(quiz)$/i, "$1zes");
43
44/**
45 * Default singularization rules.
46 */
47
481en.singular(/s$/i, "")
49 .singular(/(bu|mis|kis)s$/i, "$1s")
50 .singular(/([ti])a$/i, "$1um")
51 .singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, "$1$2sis")
52 .singular(/(^analy)ses$/i, "$1sis")
53 .singular(/([^f])ves$/i, "$1fe")
54 .singular(/([lr])ves$/i, "$1f")
55 .singular(/ies$/i, "ie")
56 .singular(/([^aeiouy]|qu)ies$/i, "$1y")
57 .singular(/(series)$/i, "$1")
58 .singular(/(mov)ies$/i, "$1ie")
59 .singular(/(x|ch|ss|sh)es$/i, "$1")
60 .singular(/([m|l])ice$/i, "$1ouse")
61 .singular(/(bus)es$/i, "$1")
62 .singular(/(o)es$/i, "$1")
63 .singular(/(shoe)s$/i, "$1")
64 .singular(/(cris|ax|test)es$/i, "$1is")
65 .singular(/(octop|vir)i$/i, "$1us")
66 .singular(/(alias|status)es$/i, "$1")
67 .singular(/^(ox)en/i, "$1")
68 .singular(/(vert|ind)ices$/i, "$1ex")
69 .singular(/(matr)ices$/i, "$1ix")
70 .singular(/(quiz)zes$/i, "$1");
71
72/**
73 * Default irregular word mappings.
74 */
75
761en.irregular('i', 'we')
77 .irregular('person', 'people')
78 .irregular('man', 'men')
79 .irregular('child', 'children')
80 .irregular('move', 'moves')
81 .irregular('she', 'they')
82 .irregular('he', 'they')
83 .irregular('myself', 'ourselves')
84 .irregular('yourself', 'ourselves')
85 .irregular('himself', 'themselves')
86 .irregular('herself', 'themselves')
87 .irregular('themself', 'themselves')
88 .irregular('mine', 'ours')
89 .irregular('hers', 'theirs')
90 .irregular('his', 'theirs')
91 .irregular('its', 'theirs')
92 .irregular('theirs', 'theirs')
93 .irregular('sex', 'sexes')
94 .irregular('video', 'videos')
95 .irregular('rodeo', 'rodeos');
96
97/**
98 * Default uncountables.
99 */
100
1011en.uncountable('advice')
102 .uncountable('enegery')
103 .uncountable('excretion')
104 .uncountable('digestion')
105 .uncountable('cooperation')
106 .uncountable('health')
107 .uncountable('justice')
108 .uncountable('jeans')
109 .uncountable('labour')
110 .uncountable('machinery')
111 .uncountable('equipment')
112 .uncountable('information')
113 .uncountable('pollution')
114 .uncountable('sewage')
115 .uncountable('paper')
116 .uncountable('money')
117 .uncountable('species')
118 .uncountable('series')
119 .uncountable('rain')
120 .uncountable('rice')
121 .uncountable('fish')
122 .uncountable('sheep')
123 .uncountable('moose')
124 .uncountable('deer')
125 .uncountable('bison')
126 .uncountable('proceedings')
127 .uncountable('shears')
128 .uncountable('pincers')
129 .uncountable('breeches')
130 .uncountable('hijinks')
131 .uncountable('clippers')
132 .uncountable('chassis')
133 .uncountable('innings')
134 .uncountable('elk')
135 .uncountable('rhinoceros')
136 .uncountable('swine')
137 .uncountable('you')
138 .uncountable('news');
139

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/baucis/node_modules/lingo/lib/languages/es.js

100%
7
7
0
LineHitsSource
1/*!
2 * Lingo - languages - Spanish
3 * Copyright(c) 2010 Pau Ramon <masylum@gmail.com>
4 * Based on Bermi's Python inflector http://github.com/bermi/Python-Inflector
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Language = require('../language');
13
14/**
15 * English.
16 */
17
181var es = module.exports = new Language('es', 'Español');
19
20/**
21 * Number pluraluzation rule
22 */
231es.pluralNumbers(/[^1]/);
24
25/**
26 * Default pluralization rules.
27 */
28
291es.plural(/$/, "es")
30 .plural(/(ng|[wckgtp])$/i, "$1s")
31 .plural(/([íú])$/i, "$1es")
32 .plural(/z$/i, "ces")
33 .plural(/([éí])(s)$/i, "$1$2es")
34 .plural(/([aeiou])s$/i, "$1s")
35 .plural(/([aeiouáéó])$/i, "$1s")
36 .plural(/(^[bcdfghjklmnñpqrstvwxyz]*)([aeiou])([ns])$/i, "$1$2$3es")
37 .plural(/([áéíóú])s$/i, "$1ses")
38 .plural(/(^[bcdfghjklmnñpqrstvwxyz]*)an$/i, "$1anes")
39 .plural(/([á])([ns])$/i, "a$2es")
40 .plural(/([é])([ns])$/i, "e$2es")
41 .plural(/([í])([ns])$/i, "i$2es")
42 .plural(/([ó])([ns])$/i, "o$2es")
43 .plural(/([ú])([ns])$/i, "u$2es")
44 .plural(/([aeiou])x$/i, "$1x");
45
46/**
47 * Default singularization rules.
48 */
49
501es.singular(/es$/i, "")
51 .singular(/([ghñpv]e)s$/i, "$1")
52 .singular(/([bcdfghjklmnñprstvwxyz]{2,}e)s$/i, "$1")
53 .singular(/([^e])s$/i, "$1")
54 .singular(/(é)s$/i, "$1")
55 .singular(/(sis|tis|xis)+$/i, "$1")
56 .singular(/(ces)$/i, "z")
57 .singular(/oides$/i, "oide")
58 .singular(/([a])([ns])es$/i, "á$2")
59 .singular(/([e])([ns])es$/i, "é$2")
60 .singular(/([i])([ns])es$/i, "í$2")
61 .singular(/([o])([ns])es$/i, "ó$2")
62 .singular(/([u])([ns])es$/i, "ú$2")
63 .singular(/^([bcdfghjklmnñpqrstvwxyz]*)([aeiou])([ns])es$/i, "$1$2$3");
64
65/**
66 * Default irregular word mappings.
67 */
68
691es.irregular('país', 'países')
70 .irregular('champú', 'champús')
71 .irregular('jersey', 'jerséis')
72 .irregular('carácter', 'caracteres')
73 .irregular('espécimen', 'especímenes')
74 .irregular('menú', 'menús')
75 .irregular('régimen', 'regímenes')
76 .irregular('curriculum', 'currículos')
77 .irregular('ultimátum', 'ultimatos')
78 .irregular('memorándum', 'memorandos')
79 .irregular('referéndum', 'referendos')
80
81/**
82 * Default uncountables.
83 */
84
851es.uncountable('tijeras')
86 .uncountable('gafas')
87 .uncountable('agua')
88 .uncountable('vacaciones')
89 .uncountable('víveres')
90 .uncountable('déficit')
91
92

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/baucis/node_modules/lingo/lib/lingo.js

43%
23
10
13
LineHitsSource
1
2/*!
3 * Lingo
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var fs = require('fs');
13
14/**
15 * Library version.
16 *
17 * @type String
18 */
19
201exports.version = '0.0.4';
21
22/**
23 * Expose `Language`.
24 *
25 * @type Function
26 */
27
281exports.Language = require('./language');
29
30/**
31 * Extend `Language` with inflection rules.
32 */
33
341require('./inflection');
35
36/**
37 * Auto-require languages.
38 */
39
401require('./languages/en');
411require('./languages/es');
42
43/**
44 * Capitalize the first word of `str` or optionally `allWords`.
45 *
46 * Examples:
47 *
48 * lingo.capitalize('hello there');
49 * // => "Hello there"
50 *
51 * lingo.capitalize('hello there', true);
52 * // => "Hello There"
53 *
54 * @param {String} str
55 * @param {Boolean} allWords
56 * @return {String}
57 * @api public
58 */
59
601exports.capitalize = function(str, allWords){
610 if (allWords) {
620 return str.split(' ').map(function(word){
630 return exports.capitalize(word);
64 }).join(' ');
65 }
660 return str.charAt(0).toUpperCase() + str.substr(1);
67};
68
69/**
70 * Camel-case the given `str`.
71 *
72 * Examples:
73 *
74 * lingo.camelcase('foo bar');
75 * // => "fooBar"
76 *
77 * lingo.camelcase('foo bar baz', true);
78 * // => "FooBarBaz"
79 *
80 * @param {String} str
81 * @param {Boolean} uppercaseFirst
82 * @return {String}
83 * @api public
84 */
85
861exports.camelcase = function(str, uppercaseFirst){
870 return str.replace(/[^\w\d ]+/g, '').split(' ').map(function(word, i){
880 if (i || (0 == i && uppercaseFirst)) {
890 word = exports.capitalize(word);
90 }
910 return word;
92 }).join('');
93};
94
95/**
96 * Underscore the given `str`.
97 *
98 * Examples:
99 *
100 * lingo.underscore('UserAccount');
101 * // => "user_account"
102 *
103 * lingo.underscore('User');
104 * // => "user"
105 *
106 * @param {String} str
107 * @return {String}
108 * @api public
109 */
110
1111exports.underscore = function(str){
1120 return str.replace(/([a-z\d])([A-Z])/g, '$1_$2').toLowerCase();
113};
114
115/**
116 * Join an array with the given `last` string
117 * which defaults to "and".
118 *
119 * Examples:
120 *
121 * lingo.join(['fruits', 'veggies', 'sugar']);
122 * // => "fruits, veggies and sugar"
123 *
124 * lingo.join(['fruits', 'veggies', 'sugar'], 'or');
125 * // => "fruits, veggies or sugar"
126 *
127 * @param {Array} arr
128 * @param {String} last
129 * @return {String}
130 * @api public
131 */
132
1331exports.join = function(arr, last){
1340 var str = arr.pop()
135 , last = last || 'and';
1360 if (arr.length) {
1370 str = arr.join(', ') + ' ' + last + ' ' + str;
138 }
1390 return str;
140};
141

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/lib/application.js

48%
127
61
66
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var connect = require('connect')
6 , Router = require('./router')
7 , methods = require('methods')
8 , middleware = require('./middleware')
9 , debug = require('debug')('express:application')
10 , locals = require('./utils').locals
11 , View = require('./view')
12 , utils = connect.utils
13 , http = require('http');
14
15/**
16 * Application prototype.
17 */
18
191var app = exports = module.exports = {};
20
21/**
22 * Initialize the server.
23 *
24 * - setup default configuration
25 * - setup default middleware
26 * - setup route reflection methods
27 *
28 * @api private
29 */
30
311app.init = function(){
321 this.cache = {};
331 this.settings = {};
341 this.engines = {};
351 this.defaultConfiguration();
36};
37
38/**
39 * Initialize application configuration.
40 *
41 * @api private
42 */
43
441app.defaultConfiguration = function(){
45 // default settings
461 this.enable('x-powered-by');
471 this.enable('etag');
481 this.set('env', process.env.NODE_ENV || 'development');
491 this.set('subdomain offset', 2);
501 debug('booting in %s mode', this.get('env'));
51
52 // implicit middleware
531 this.use(connect.query());
541 this.use(middleware.init(this));
55
56 // inherit protos
571 this.on('mount', function(parent){
580 this.request.__proto__ = parent.request;
590 this.response.__proto__ = parent.response;
600 this.engines.__proto__ = parent.engines;
610 this.settings.__proto__ = parent.settings;
62 });
63
64 // router
651 this._router = new Router(this);
661 this.routes = this._router.map;
671 this.__defineGetter__('router', function(){
680 this._usedRouter = true;
690 this._router.caseSensitive = this.enabled('case sensitive routing');
700 this._router.strict = this.enabled('strict routing');
710 return this._router.middleware;
72 });
73
74 // setup locals
751 this.locals = locals(this);
76
77 // default locals
781 this.locals.settings = this.settings;
79
80 // default configuration
811 this.set('view', View);
821 this.set('views', process.cwd() + '/views');
831 this.set('jsonp callback name', 'callback');
84
851 this.configure('development', function(){
861 this.set('json spaces', 2);
87 });
88
891 this.configure('production', function(){
900 this.enable('view cache');
91 });
92};
93
94/**
95 * Proxy `connect#use()` to apply settings to
96 * mounted applications.
97 *
98 * @param {String|Function|Server} route
99 * @param {Function|Server} fn
100 * @return {app} for chaining
101 * @api public
102 */
103
1041app.use = function(route, fn){
1052 var app;
106
107 // default route to '/'
1084 if ('string' != typeof route) fn = route, route = '/';
109
110 // express app
1112 if (fn.handle && fn.set) app = fn;
112
113 // restore .app property on req and res
1142 if (app) {
1150 app.route = route;
1160 fn = function(req, res, next) {
1170 var orig = req.app;
1180 app.handle(req, res, function(err){
1190 req.__proto__ = orig.request;
1200 res.__proto__ = orig.response;
1210 next(err);
122 });
123 };
124 }
125
1262 connect.proto.use.call(this, route, fn);
127
128 // mounted an app
1292 if (app) {
1300 app.parent = this;
1310 app.emit('mount', this);
132 }
133
1342 return this;
135};
136
137/**
138 * Register the given template engine callback `fn`
139 * as `ext`.
140 *
141 * By default will `require()` the engine based on the
142 * file extension. For example if you try to render
143 * a "foo.jade" file Express will invoke the following internally:
144 *
145 * app.engine('jade', require('jade').__express);
146 *
147 * For engines that do not provide `.__express` out of the box,
148 * or if you wish to "map" a different extension to the template engine
149 * you may use this method. For example mapping the EJS template engine to
150 * ".html" files:
151 *
152 * app.engine('html', require('ejs').renderFile);
153 *
154 * In this case EJS provides a `.renderFile()` method with
155 * the same signature that Express expects: `(path, options, callback)`,
156 * though note that it aliases this method as `ejs.__express` internally
157 * so if you're using ".ejs" extensions you dont need to do anything.
158 *
159 * Some template engines do not follow this convention, the
160 * [Consolidate.js](https://github.com/visionmedia/consolidate.js)
161 * library was created to map all of node's popular template
162 * engines to follow this convention, thus allowing them to
163 * work seamlessly within Express.
164 *
165 * @param {String} ext
166 * @param {Function} fn
167 * @return {app} for chaining
168 * @api public
169 */
170
1711app.engine = function(ext, fn){
1720 if ('function' != typeof fn) throw new Error('callback function required');
1730 if ('.' != ext[0]) ext = '.' + ext;
1740 this.engines[ext] = fn;
1750 return this;
176};
177
178/**
179 * Map the given param placeholder `name`(s) to the given callback(s).
180 *
181 * Parameter mapping is used to provide pre-conditions to routes
182 * which use normalized placeholders. For example a _:user_id_ parameter
183 * could automatically load a user's information from the database without
184 * any additional code,
185 *
186 * The callback uses the same signature as middleware, the only difference
187 * being that the value of the placeholder is passed, in this case the _id_
188 * of the user. Once the `next()` function is invoked, just like middleware
189 * it will continue on to execute the route, or subsequent parameter functions.
190 *
191 * app.param('user_id', function(req, res, next, id){
192 * User.find(id, function(err, user){
193 * if (err) {
194 * next(err);
195 * } else if (user) {
196 * req.user = user;
197 * next();
198 * } else {
199 * next(new Error('failed to load user'));
200 * }
201 * });
202 * });
203 *
204 * @param {String|Array} name
205 * @param {Function} fn
206 * @return {app} for chaining
207 * @api public
208 */
209
2101app.param = function(name, fn){
2110 var self = this
212 , fns = [].slice.call(arguments, 1);
213
214 // array
2150 if (Array.isArray(name)) {
2160 name.forEach(function(name){
2170 fns.forEach(function(fn){
2180 self.param(name, fn);
219 });
220 });
221 // param logic
2220 } else if ('function' == typeof name) {
2230 this._router.param(name);
224 // single
225 } else {
2260 if (':' == name[0]) name = name.substr(1);
2270 fns.forEach(function(fn){
2280 self._router.param(name, fn);
229 });
230 }
231
2320 return this;
233};
234
235/**
236 * Assign `setting` to `val`, or return `setting`'s value.
237 *
238 * app.set('foo', 'bar');
239 * app.get('foo');
240 * // => "bar"
241 *
242 * Mounted servers inherit their parent server's settings.
243 *
244 * @param {String} setting
245 * @param {String} val
246 * @return {Server} for chaining
247 * @api public
248 */
249
2501app.set = function(setting, val){
25110 if (1 == arguments.length) {
2521 return this.settings[setting];
253 } else {
2549 this.settings[setting] = val;
2559 return this;
256 }
257};
258
259/**
260 * Return the app's absolute pathname
261 * based on the parent(s) that have
262 * mounted it.
263 *
264 * For example if the application was
265 * mounted as "/admin", which itself
266 * was mounted as "/blog" then the
267 * return value would be "/blog/admin".
268 *
269 * @return {String}
270 * @api private
271 */
272
2731app.path = function(){
2740 return this.parent
275 ? this.parent.path() + this.route
276 : '';
277};
278
279/**
280 * Check if `setting` is enabled (truthy).
281 *
282 * app.enabled('foo')
283 * // => false
284 *
285 * app.enable('foo')
286 * app.enabled('foo')
287 * // => true
288 *
289 * @param {String} setting
290 * @return {Boolean}
291 * @api public
292 */
293
2941app.enabled = function(setting){
2950 return !!this.set(setting);
296};
297
298/**
299 * Check if `setting` is disabled.
300 *
301 * app.disabled('foo')
302 * // => true
303 *
304 * app.enable('foo')
305 * app.disabled('foo')
306 * // => false
307 *
308 * @param {String} setting
309 * @return {Boolean}
310 * @api public
311 */
312
3131app.disabled = function(setting){
3140 return !this.set(setting);
315};
316
317/**
318 * Enable `setting`.
319 *
320 * @param {String} setting
321 * @return {app} for chaining
322 * @api public
323 */
324
3251app.enable = function(setting){
3262 return this.set(setting, true);
327};
328
329/**
330 * Disable `setting`.
331 *
332 * @param {String} setting
333 * @return {app} for chaining
334 * @api public
335 */
336
3371app.disable = function(setting){
3380 return this.set(setting, false);
339};
340
341/**
342 * Configure callback for zero or more envs,
343 * when no `env` is specified that callback will
344 * be invoked for all environments. Any combination
345 * can be used multiple times, in any order desired.
346 *
347 * Examples:
348 *
349 * app.configure(function(){
350 * // executed for all envs
351 * });
352 *
353 * app.configure('stage', function(){
354 * // executed staging env
355 * });
356 *
357 * app.configure('stage', 'production', function(){
358 * // executed for stage and production
359 * });
360 *
361 * Note:
362 *
363 * These callbacks are invoked immediately, and
364 * are effectively sugar for the following:
365 *
366 * var env = process.env.NODE_ENV || 'development';
367 *
368 * switch (env) {
369 * case 'development':
370 * ...
371 * break;
372 * case 'stage':
373 * ...
374 * break;
375 * case 'production':
376 * ...
377 * break;
378 * }
379 *
380 * @param {String} env...
381 * @param {Function} fn
382 * @return {app} for chaining
383 * @api public
384 */
385
3861app.configure = function(env, fn){
3872 var envs = 'all'
388 , args = [].slice.call(arguments);
3892 fn = args.pop();
3904 if (args.length) envs = args;
3913 if ('all' == envs || ~envs.indexOf(this.settings.env)) fn.call(this);
3922 return this;
393};
394
395/**
396 * Delegate `.VERB(...)` calls to `router.VERB(...)`.
397 */
398
3991methods.forEach(function(method){
40024 app[method] = function(path){
4012 if ('get' == method && 1 == arguments.length) return this.set(path);
402
403 // deprecated
4040 if (Array.isArray(path)) {
4050 console.trace('passing an array to app.VERB() is deprecated and will be removed in 4.0');
406 }
407
408 // if no router attached yet, attach the router
4090 if (!this._usedRouter) this.use(this.router);
410
411 // setup route
4120 this._router[method].apply(this._router, arguments);
4130 return this;
414 };
415});
416
417/**
418 * Special-cased "all" method, applying the given route `path`,
419 * middleware, and callback to _every_ HTTP method.
420 *
421 * @param {String} path
422 * @param {Function} ...
423 * @return {app} for chaining
424 * @api public
425 */
426
4271app.all = function(path){
4280 var args = arguments;
4290 methods.forEach(function(method){
4300 app[method].apply(this, args);
431 }, this);
4320 return this;
433};
434
435// del -> delete alias
436
4371app.del = app.delete;
438
439/**
440 * Render the given view `name` name with `options`
441 * and a callback accepting an error and the
442 * rendered template string.
443 *
444 * Example:
445 *
446 * app.render('email', { name: 'Tobi' }, function(err, html){
447 * // ...
448 * })
449 *
450 * @param {String} name
451 * @param {String|Function} options or fn
452 * @param {Function} fn
453 * @api public
454 */
455
4561app.render = function(name, options, fn){
4570 var opts = {}
458 , cache = this.cache
459 , engines = this.engines
460 , view;
461
462 // support callback function as second arg
4630 if ('function' == typeof options) {
4640 fn = options, options = {};
465 }
466
467 // merge app.locals
4680 utils.merge(opts, this.locals);
469
470 // merge options._locals
4710 if (options._locals) utils.merge(opts, options._locals);
472
473 // merge options
4740 utils.merge(opts, options);
475
476 // set .cache unless explicitly provided
4770 opts.cache = null == opts.cache
478 ? this.enabled('view cache')
479 : opts.cache;
480
481 // primed cache
4820 if (opts.cache) view = cache[name];
483
484 // view
4850 if (!view) {
4860 view = new (this.get('view'))(name, {
487 defaultEngine: this.get('view engine'),
488 root: this.get('views'),
489 engines: engines
490 });
491
4920 if (!view.path) {
4930 var err = new Error('Failed to lookup view "' + name + '" in views directory "' + view.root + '"');
4940 err.view = view;
4950 return fn(err);
496 }
497
498 // prime the cache
4990 if (opts.cache) cache[name] = view;
500 }
501
502 // render
5030 try {
5040 view.render(opts, fn);
505 } catch (err) {
5060 fn(err);
507 }
508};
509
510/**
511 * Listen for connections.
512 *
513 * A node `http.Server` is returned, with this
514 * application (which is a `Function`) as its
515 * callback. If you wish to create both an HTTP
516 * and HTTPS server you may do so with the "http"
517 * and "https" modules as shown here:
518 *
519 * var http = require('http')
520 * , https = require('https')
521 * , express = require('express')
522 * , app = express();
523 *
524 * http.createServer(app).listen(80);
525 * https.createServer({ ... }, app).listen(443);
526 *
527 * @return {http.Server}
528 * @api public
529 */
530
5311app.listen = function(){
5320 var server = http.createServer(this);
5330 return server.listen.apply(server, arguments);
534};
535

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/lib/express.js

70%
27
19
8
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var merge = require('merge-descriptors');
61var connect = require('connect')
7 , proto = require('./application')
8 , Route = require('./router/route')
9 , Router = require('./router')
10 , req = require('./request')
11 , res = require('./response')
12 , utils = connect.utils;
13
14/**
15 * Expose `createApplication()`.
16 */
17
181exports = module.exports = createApplication;
19
20/**
21 * Expose mime.
22 */
23
241exports.mime = connect.mime;
25
26/**
27 * Create an express application.
28 *
29 * @return {Function}
30 * @api public
31 */
32
331function createApplication() {
341 var app = connect();
351 utils.merge(app, proto);
361 app.request = { __proto__: req, app: app };
371 app.response = { __proto__: res, app: app };
381 app.init();
391 return app;
40}
41
42/**
43 * Expose connect.middleware as express.*
44 * for example `express.logger` etc.
45 */
46
471merge(exports, connect.middleware);
48
49/**
50 * Error on createServer().
51 */
52
531exports.createServer = function(){
540 console.warn('Warning: express.createServer() is deprecated, express');
550 console.warn('applications no longer inherit from http.Server,');
560 console.warn('please use:');
570 console.warn('');
580 console.warn(' var express = require("express");');
590 console.warn(' var app = express();');
600 console.warn('');
610 return createApplication();
62};
63
64/**
65 * Expose the prototypes.
66 */
67
681exports.application = proto;
691exports.request = req;
701exports.response = res;
71
72/**
73 * Expose constructors.
74 */
75
761exports.Route = Route;
771exports.Router = Router;
78
79// Error handler title
80
811exports.errorHandler.title = 'Express';
82
83

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/lib/middleware.js

27%
11
3
8
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var utils = require('./utils');
7
8/**
9 * Initialization middleware, exposing the
10 * request and response to eachother, as well
11 * as defaulting the X-Powered-By header field.
12 *
13 * @param {Function} app
14 * @return {Function}
15 * @api private
16 */
17
181exports.init = function(app){
191 return function expressInit(req, res, next){
200 if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express');
210 req.res = res;
220 res.req = req;
230 req.next = next;
24
250 req.__proto__ = app.request;
260 res.__proto__ = app.response;
27
280 res.locals = res.locals || utils.locals(res);
29
300 next();
31 }
32};
33

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/lib/request.js

24%
102
25
77
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var http = require('http')
7 , utils = require('./utils')
8 , connect = require('connect')
9 , fresh = require('fresh')
10 , parseRange = require('range-parser')
11 , parse = connect.utils.parseUrl
12 , mime = connect.mime;
13
14/**
15 * Request prototype.
16 */
17
181var req = exports = module.exports = {
19 __proto__: http.IncomingMessage.prototype
20};
21
22/**
23 * Return request header.
24 *
25 * The `Referrer` header field is special-cased,
26 * both `Referrer` and `Referer` are interchangeable.
27 *
28 * Examples:
29 *
30 * req.get('Content-Type');
31 * // => "text/plain"
32 *
33 * req.get('content-type');
34 * // => "text/plain"
35 *
36 * req.get('Something');
37 * // => undefined
38 *
39 * Aliased as `req.header()`.
40 *
41 * @param {String} name
42 * @return {String}
43 * @api public
44 */
45
461req.get =
47req.header = function(name){
480 switch (name = name.toLowerCase()) {
49 case 'referer':
50 case 'referrer':
510 return this.headers.referrer
52 || this.headers.referer;
53 default:
540 return this.headers[name];
55 }
56};
57
58/**
59 * Check if the given `type(s)` is acceptable, returning
60 * the best match when true, otherwise `undefined`, in which
61 * case you should respond with 406 "Not Acceptable".
62 *
63 * The `type` value may be a single mime type string
64 * such as "application/json", the extension name
65 * such as "json", a comma-delimted list such as "json, html, text/plain",
66 * an argument list such as `"json", "html", "text/plain"`,
67 * or an array `["json", "html", "text/plain"]`. When a list
68 * or array is given the _best_ match, if any is returned.
69 *
70 * Examples:
71 *
72 * // Accept: text/html
73 * req.accepts('html');
74 * // => "html"
75 *
76 * // Accept: text/*, application/json
77 * req.accepts('html');
78 * // => "html"
79 * req.accepts('text/html');
80 * // => "text/html"
81 * req.accepts('json, text');
82 * // => "json"
83 * req.accepts('application/json');
84 * // => "application/json"
85 *
86 * // Accept: text/*, application/json
87 * req.accepts('image/png');
88 * req.accepts('png');
89 * // => undefined
90 *
91 * // Accept: text/*;q=.5, application/json
92 * req.accepts(['html', 'json']);
93 * req.accepts('html', 'json');
94 * req.accepts('html, json');
95 * // => "json"
96 *
97 * @param {String|Array} type(s)
98 * @return {String}
99 * @api public
100 */
101
1021req.accepts = function(type){
1030 var args = arguments.length > 1 ? [].slice.apply(arguments) : type;
1040 return utils.accepts(args, this.get('Accept'));
105};
106
107/**
108 * Check if the given `encoding` is accepted.
109 *
110 * @param {String} encoding
111 * @return {Boolean}
112 * @api public
113 */
114
1151req.acceptsEncoding = function(encoding){
1160 return !! ~this.acceptedEncodings.indexOf(encoding);
117};
118
119/**
120 * Check if the given `charset` is acceptable,
121 * otherwise you should respond with 406 "Not Acceptable".
122 *
123 * @param {String} charset
124 * @return {Boolean}
125 * @api public
126 */
127
1281req.acceptsCharset = function(charset){
1290 var accepted = this.acceptedCharsets;
1300 return accepted.length
131 ? !! ~accepted.indexOf(charset)
132 : true;
133};
134
135/**
136 * Check if the given `lang` is acceptable,
137 * otherwise you should respond with 406 "Not Acceptable".
138 *
139 * @param {String} lang
140 * @return {Boolean}
141 * @api public
142 */
143
1441req.acceptsLanguage = function(lang){
1450 var accepted = this.acceptedLanguages;
1460 return accepted.length
147 ? !! ~accepted.indexOf(lang)
148 : true;
149};
150
151/**
152 * Parse Range header field,
153 * capping to the given `size`.
154 *
155 * Unspecified ranges such as "0-" require
156 * knowledge of your resource length. In
157 * the case of a byte range this is of course
158 * the total number of bytes. If the Range
159 * header field is not given `null` is returned,
160 * `-1` when unsatisfiable, `-2` when syntactically invalid.
161 *
162 * NOTE: remember that ranges are inclusive, so
163 * for example "Range: users=0-3" should respond
164 * with 4 users when available, not 3.
165 *
166 * @param {Number} size
167 * @return {Array}
168 * @api public
169 */
170
1711req.range = function(size){
1720 var range = this.get('Range');
1730 if (!range) return;
1740 return parseRange(size, range);
175};
176
177/**
178 * Return an array of encodings.
179 *
180 * Examples:
181 *
182 * ['gzip', 'deflate']
183 *
184 * @return {Array}
185 * @api public
186 */
187
1881req.__defineGetter__('acceptedEncodings', function(){
1890 var accept = this.get('Accept-Encoding');
1900 return accept
191 ? accept.trim().split(/ *, */)
192 : [];
193});
194
195/**
196 * Return an array of Accepted media types
197 * ordered from highest quality to lowest.
198 *
199 * Examples:
200 *
201 * [ { value: 'application/json',
202 * quality: 1,
203 * type: 'application',
204 * subtype: 'json' },
205 * { value: 'text/html',
206 * quality: 0.5,
207 * type: 'text',
208 * subtype: 'html' } ]
209 *
210 * @return {Array}
211 * @api public
212 */
213
2141req.__defineGetter__('accepted', function(){
2150 var accept = this.get('Accept');
2160 return accept
217 ? utils.parseAccept(accept)
218 : [];
219});
220
221/**
222 * Return an array of Accepted languages
223 * ordered from highest quality to lowest.
224 *
225 * Examples:
226 *
227 * Accept-Language: en;q=.5, en-us
228 * ['en-us', 'en']
229 *
230 * @return {Array}
231 * @api public
232 */
233
2341req.__defineGetter__('acceptedLanguages', function(){
2350 var accept = this.get('Accept-Language');
2360 return accept
237 ? utils
238 .parseParams(accept)
239 .map(function(obj){
2400 return obj.value;
241 })
242 : [];
243});
244
245/**
246 * Return an array of Accepted charsets
247 * ordered from highest quality to lowest.
248 *
249 * Examples:
250 *
251 * Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8
252 * ['unicode-1-1', 'iso-8859-5']
253 *
254 * @return {Array}
255 * @api public
256 */
257
2581req.__defineGetter__('acceptedCharsets', function(){
2590 var accept = this.get('Accept-Charset');
2600 return accept
261 ? utils
262 .parseParams(accept)
263 .map(function(obj){
2640 return obj.value;
265 })
266 : [];
267});
268
269/**
270 * Return the value of param `name` when present or `defaultValue`.
271 *
272 * - Checks route placeholders, ex: _/user/:id_
273 * - Checks body params, ex: id=12, {"id":12}
274 * - Checks query string params, ex: ?id=12
275 *
276 * To utilize request bodies, `req.body`
277 * should be an object. This can be done by using
278 * the `connect.bodyParser()` middleware.
279 *
280 * @param {String} name
281 * @param {Mixed} [defaultValue]
282 * @return {String}
283 * @api public
284 */
285
2861req.param = function(name, defaultValue){
2870 var params = this.params || {};
2880 var body = this.body || {};
2890 var query = this.query || {};
2900 if (null != params[name] && params.hasOwnProperty(name)) return params[name];
2910 if (null != body[name]) return body[name];
2920 if (null != query[name]) return query[name];
2930 return defaultValue;
294};
295
296/**
297 * Check if the incoming request contains the "Content-Type"
298 * header field, and it contains the give mime `type`.
299 *
300 * Examples:
301 *
302 * // With Content-Type: text/html; charset=utf-8
303 * req.is('html');
304 * req.is('text/html');
305 * req.is('text/*');
306 * // => true
307 *
308 * // When Content-Type is application/json
309 * req.is('json');
310 * req.is('application/json');
311 * req.is('application/*');
312 * // => true
313 *
314 * req.is('html');
315 * // => false
316 *
317 * @param {String} type
318 * @return {Boolean}
319 * @api public
320 */
321
3221req.is = function(type){
3230 var ct = this.get('Content-Type');
3240 if (!ct) return false;
3250 ct = ct.split(';')[0];
3260 if (!~type.indexOf('/')) type = mime.lookup(type);
3270 if (~type.indexOf('*')) {
3280 type = type.split('/');
3290 ct = ct.split('/');
3300 if ('*' == type[0] && type[1] == ct[1]) return true;
3310 if ('*' == type[1] && type[0] == ct[0]) return true;
3320 return false;
333 }
3340 return !! ~ct.indexOf(type);
335};
336
337/**
338 * Return the protocol string "http" or "https"
339 * when requested with TLS. When the "trust proxy"
340 * setting is enabled the "X-Forwarded-Proto" header
341 * field will be trusted. If you're running behind
342 * a reverse proxy that supplies https for you this
343 * may be enabled.
344 *
345 * @return {String}
346 * @api public
347 */
348
3491req.__defineGetter__('protocol', function(){
3500 var trustProxy = this.app.get('trust proxy');
3510 if (this.connection.encrypted) return 'https';
3520 if (!trustProxy) return 'http';
3530 var proto = this.get('X-Forwarded-Proto') || 'http';
3540 return proto.split(/\s*,\s*/)[0];
355});
356
357/**
358 * Short-hand for:
359 *
360 * req.protocol == 'https'
361 *
362 * @return {Boolean}
363 * @api public
364 */
365
3661req.__defineGetter__('secure', function(){
3670 return 'https' == this.protocol;
368});
369
370/**
371 * Return the remote address, or when
372 * "trust proxy" is `true` return
373 * the upstream addr.
374 *
375 * @return {String}
376 * @api public
377 */
378
3791req.__defineGetter__('ip', function(){
3800 return this.ips[0] || this.connection.remoteAddress;
381});
382
383/**
384 * When "trust proxy" is `true`, parse
385 * the "X-Forwarded-For" ip address list.
386 *
387 * For example if the value were "client, proxy1, proxy2"
388 * you would receive the array `["client", "proxy1", "proxy2"]`
389 * where "proxy2" is the furthest down-stream.
390 *
391 * @return {Array}
392 * @api public
393 */
394
3951req.__defineGetter__('ips', function(){
3960 var trustProxy = this.app.get('trust proxy');
3970 var val = this.get('X-Forwarded-For');
3980 return trustProxy && val
399 ? val.split(/ *, */)
400 : [];
401});
402
403/**
404 * Return basic auth credentials.
405 *
406 * Examples:
407 *
408 * // http://tobi:hello@example.com
409 * req.auth
410 * // => { username: 'tobi', password: 'hello' }
411 *
412 * @return {Object} or undefined
413 * @api public
414 */
415
4161req.__defineGetter__('auth', function(){
417 // missing
4180 var auth = this.get('Authorization');
4190 if (!auth) return;
420
421 // malformed
4220 var parts = auth.split(' ');
4230 if ('basic' != parts[0].toLowerCase()) return;
4240 if (!parts[1]) return;
4250 auth = parts[1];
426
427 // credentials
4280 auth = new Buffer(auth, 'base64').toString().match(/^([^:]*):(.*)$/);
4290 if (!auth) return;
4300 return { username: auth[1], password: auth[2] };
431});
432
433/**
434 * Return subdomains as an array.
435 *
436 * Subdomains are the dot-separated parts of the host before the main domain of
437 * the app. By default, the domain of the app is assumed to be the last two
438 * parts of the host. This can be changed by setting "subdomain offset".
439 *
440 * For example, if the domain is "tobi.ferrets.example.com":
441 * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`.
442 * If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
443 *
444 * @return {Array}
445 * @api public
446 */
447
4481req.__defineGetter__('subdomains', function(){
4490 var offset = this.app.get('subdomain offset');
4500 return (this.host || '')
451 .split('.')
452 .reverse()
453 .slice(offset);
454});
455
456/**
457 * Short-hand for `url.parse(req.url).pathname`.
458 *
459 * @return {String}
460 * @api public
461 */
462
4631req.__defineGetter__('path', function(){
4640 return parse(this).pathname;
465});
466
467/**
468 * Parse the "Host" header field hostname.
469 *
470 * @return {String}
471 * @api public
472 */
473
4741req.__defineGetter__('host', function(){
4750 var trustProxy = this.app.get('trust proxy');
4760 var host = trustProxy && this.get('X-Forwarded-Host');
4770 host = host || this.get('Host');
4780 if (!host) return;
4790 return host.split(':')[0];
480});
481
482/**
483 * Check if the request is fresh, aka
484 * Last-Modified and/or the ETag
485 * still match.
486 *
487 * @return {Boolean}
488 * @api public
489 */
490
4911req.__defineGetter__('fresh', function(){
4920 var method = this.method;
4930 var s = this.res.statusCode;
494
495 // GET or HEAD for weak freshness validation only
4960 if ('GET' != method && 'HEAD' != method) return false;
497
498 // 2xx or 304 as per rfc2616 14.26
4990 if ((s >= 200 && s < 300) || 304 == s) {
5000 return fresh(this.headers, this.res._headers);
501 }
502
5030 return false;
504});
505
506/**
507 * Check if the request is stale, aka
508 * "Last-Modified" and / or the "ETag" for the
509 * resource has changed.
510 *
511 * @return {Boolean}
512 * @api public
513 */
514
5151req.__defineGetter__('stale', function(){
5160 return !this.fresh;
517});
518
519/**
520 * Check if the request was an _XMLHttpRequest_.
521 *
522 * @return {Boolean}
523 * @api public
524 */
525
5261req.__defineGetter__('xhr', function(){
5270 var val = this.get('X-Requested-With') || '';
5280 return 'xmlhttprequest' == val.toLowerCase();
529});
530

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/lib/response.js

9%
222
20
202
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var http = require('http')
6 , path = require('path')
7 , connect = require('connect')
8 , utils = connect.utils
9 , sign = require('cookie-signature').sign
10 , normalizeType = require('./utils').normalizeType
11 , normalizeTypes = require('./utils').normalizeTypes
12 , etag = require('./utils').etag
13 , statusCodes = http.STATUS_CODES
14 , cookie = require('cookie')
15 , send = require('send')
16 , mime = connect.mime
17 , resolve = require('url').resolve
18 , basename = path.basename
19 , extname = path.extname;
20
21/**
22 * Response prototype.
23 */
24
251var res = module.exports = {
26 __proto__: http.ServerResponse.prototype
27};
28
29/**
30 * Set status `code`.
31 *
32 * @param {Number} code
33 * @return {ServerResponse}
34 * @api public
35 */
36
371res.status = function(code){
380 this.statusCode = code;
390 return this;
40};
41
42/**
43 * Set Link header field with the given `links`.
44 *
45 * Examples:
46 *
47 * res.links({
48 * next: 'http://api.example.com/users?page=2',
49 * last: 'http://api.example.com/users?page=5'
50 * });
51 *
52 * @param {Object} links
53 * @return {ServerResponse}
54 * @api public
55 */
56
571res.links = function(links){
580 var link = this.get('Link') || '';
590 if (link) link += ', ';
600 return this.set('Link', link + Object.keys(links).map(function(rel){
610 return '<' + links[rel] + '>; rel="' + rel + '"';
62 }).join(', '));
63};
64
65/**
66 * Send a response.
67 *
68 * Examples:
69 *
70 * res.send(new Buffer('wahoo'));
71 * res.send({ some: 'json' });
72 * res.send('<p>some html</p>');
73 * res.send(404, 'Sorry, cant find that');
74 * res.send(404);
75 *
76 * @param {Mixed} body or status
77 * @param {Mixed} body
78 * @return {ServerResponse}
79 * @api public
80 */
81
821res.send = function(body){
830 var req = this.req;
840 var head = 'HEAD' == req.method;
850 var len;
86
87 // settings
880 var app = this.app;
89
90 // allow status / body
910 if (2 == arguments.length) {
92 // res.send(body, status) backwards compat
930 if ('number' != typeof body && 'number' == typeof arguments[1]) {
940 this.statusCode = arguments[1];
95 } else {
960 this.statusCode = body;
970 body = arguments[1];
98 }
99 }
100
1010 switch (typeof body) {
102 // response status
103 case 'number':
1040 this.get('Content-Type') || this.type('txt');
1050 this.statusCode = body;
1060 body = http.STATUS_CODES[body];
1070 break;
108 // string defaulting to html
109 case 'string':
1100 if (!this.get('Content-Type')) {
1110 this.charset = this.charset || 'utf-8';
1120 this.type('html');
113 }
1140 break;
115 case 'boolean':
116 case 'object':
1170 if (null == body) {
1180 body = '';
1190 } else if (Buffer.isBuffer(body)) {
1200 this.get('Content-Type') || this.type('bin');
121 } else {
1220 return this.json(body);
123 }
1240 break;
125 }
126
127 // populate Content-Length
1280 if (undefined !== body && !this.get('Content-Length')) {
1290 this.set('Content-Length', len = Buffer.isBuffer(body)
130 ? body.length
131 : Buffer.byteLength(body));
132 }
133
134 // ETag support
135 // TODO: W/ support
1360 if (app.settings.etag && len && 'GET' == req.method) {
1370 if (!this.get('ETag')) {
1380 this.set('ETag', etag(body));
139 }
140 }
141
142 // freshness
1430 if (req.fresh) this.statusCode = 304;
144
145 // strip irrelevant headers
1460 if (204 == this.statusCode || 304 == this.statusCode) {
1470 this.removeHeader('Content-Type');
1480 this.removeHeader('Content-Length');
1490 this.removeHeader('Transfer-Encoding');
1500 body = '';
151 }
152
153 // respond
1540 this.end(head ? null : body);
1550 return this;
156};
157
158/**
159 * Send JSON response.
160 *
161 * Examples:
162 *
163 * res.json(null);
164 * res.json({ user: 'tj' });
165 * res.json(500, 'oh noes!');
166 * res.json(404, 'I dont have that');
167 *
168 * @param {Mixed} obj or status
169 * @param {Mixed} obj
170 * @return {ServerResponse}
171 * @api public
172 */
173
1741res.json = function(obj){
175 // allow status / body
1760 if (2 == arguments.length) {
177 // res.json(body, status) backwards compat
1780 if ('number' == typeof arguments[1]) {
1790 this.statusCode = arguments[1];
180 } else {
1810 this.statusCode = obj;
1820 obj = arguments[1];
183 }
184 }
185
186 // settings
1870 var app = this.app;
1880 var replacer = app.get('json replacer');
1890 var spaces = app.get('json spaces');
1900 var body = JSON.stringify(obj, replacer, spaces);
191
192 // content-type
1930 this.charset = this.charset || 'utf-8';
1940 this.get('Content-Type') || this.set('Content-Type', 'application/json');
195
1960 return this.send(body);
197};
198
199/**
200 * Send JSON response with JSONP callback support.
201 *
202 * Examples:
203 *
204 * res.jsonp(null);
205 * res.jsonp({ user: 'tj' });
206 * res.jsonp(500, 'oh noes!');
207 * res.jsonp(404, 'I dont have that');
208 *
209 * @param {Mixed} obj or status
210 * @param {Mixed} obj
211 * @return {ServerResponse}
212 * @api public
213 */
214
2151res.jsonp = function(obj){
216 // allow status / body
2170 if (2 == arguments.length) {
218 // res.json(body, status) backwards compat
2190 if ('number' == typeof arguments[1]) {
2200 this.statusCode = arguments[1];
221 } else {
2220 this.statusCode = obj;
2230 obj = arguments[1];
224 }
225 }
226
227 // settings
2280 var app = this.app;
2290 var replacer = app.get('json replacer');
2300 var spaces = app.get('json spaces');
2310 var body = JSON.stringify(obj, replacer, spaces)
232 .replace(/\u2028/g, '\\u2028')
233 .replace(/\u2029/g, '\\u2029');
2340 var callback = this.req.query[app.get('jsonp callback name')];
235
236 // content-type
2370 this.charset = this.charset || 'utf-8';
2380 this.set('Content-Type', 'application/json');
239
240 // jsonp
2410 if (callback) {
2420 if (Array.isArray(callback)) callback = callback[0];
2430 this.set('Content-Type', 'text/javascript');
2440 var cb = callback.replace(/[^\[\]\w$.]/g, '');
2450 body = 'typeof ' + cb + ' === \'function\' && ' + cb + '(' + body + ');';
246 }
247
2480 return this.send(body);
249};
250
251/**
252 * Transfer the file at the given `path`.
253 *
254 * Automatically sets the _Content-Type_ response header field.
255 * The callback `fn(err)` is invoked when the transfer is complete
256 * or when an error occurs. Be sure to check `res.sentHeader`
257 * if you wish to attempt responding, as the header and some data
258 * may have already been transferred.
259 *
260 * Options:
261 *
262 * - `maxAge` defaulting to 0
263 * - `root` root directory for relative filenames
264 *
265 * Examples:
266 *
267 * The following example illustrates how `res.sendfile()` may
268 * be used as an alternative for the `static()` middleware for
269 * dynamic situations. The code backing `res.sendfile()` is actually
270 * the same code, so HTTP cache support etc is identical.
271 *
272 * app.get('/user/:uid/photos/:file', function(req, res){
273 * var uid = req.params.uid
274 * , file = req.params.file;
275 *
276 * req.user.mayViewFilesFrom(uid, function(yes){
277 * if (yes) {
278 * res.sendfile('/uploads/' + uid + '/' + file);
279 * } else {
280 * res.send(403, 'Sorry! you cant see that.');
281 * }
282 * });
283 * });
284 *
285 * @param {String} path
286 * @param {Object|Function} options or fn
287 * @param {Function} fn
288 * @api public
289 */
290
2911res.sendfile = function(path, options, fn){
2920 var self = this
293 , req = self.req
294 , next = this.req.next
295 , options = options || {}
296 , done;
297
298 // support function as second arg
2990 if ('function' == typeof options) {
3000 fn = options;
3010 options = {};
302 }
303
304 // socket errors
3050 req.socket.on('error', error);
306
307 // errors
3080 function error(err) {
3090 if (done) return;
3100 done = true;
311
312 // clean up
3130 cleanup();
3140 if (!self.headerSent) self.removeHeader('Content-Disposition');
315
316 // callback available
3170 if (fn) return fn(err);
318
319 // list in limbo if there's no callback
3200 if (self.headerSent) return;
321
322 // delegate
3230 next(err);
324 }
325
326 // streaming
3270 function stream(stream) {
3280 if (done) return;
3290 cleanup();
3300 if (fn) stream.on('end', fn);
331 }
332
333 // cleanup
3340 function cleanup() {
3350 req.socket.removeListener('error', error);
336 }
337
338 // transfer
3390 var file = send(req, path);
3400 if (options.root) file.root(options.root);
3410 file.maxage(options.maxAge || 0);
3420 file.on('error', error);
3430 file.on('directory', next);
3440 file.on('stream', stream);
3450 file.pipe(this);
3460 this.on('finish', cleanup);
347};
348
349/**
350 * Transfer the file at the given `path` as an attachment.
351 *
352 * Optionally providing an alternate attachment `filename`,
353 * and optional callback `fn(err)`. The callback is invoked
354 * when the data transfer is complete, or when an error has
355 * ocurred. Be sure to check `res.headerSent` if you plan to respond.
356 *
357 * This method uses `res.sendfile()`.
358 *
359 * @param {String} path
360 * @param {String|Function} filename or fn
361 * @param {Function} fn
362 * @api public
363 */
364
3651res.download = function(path, filename, fn){
366 // support function as second arg
3670 if ('function' == typeof filename) {
3680 fn = filename;
3690 filename = null;
370 }
371
3720 filename = filename || path;
3730 this.set('Content-Disposition', 'attachment; filename="' + basename(filename) + '"');
3740 return this.sendfile(path, fn);
375};
376
377/**
378 * Set _Content-Type_ response header with `type` through `mime.lookup()`
379 * when it does not contain "/", or set the Content-Type to `type` otherwise.
380 *
381 * Examples:
382 *
383 * res.type('.html');
384 * res.type('html');
385 * res.type('json');
386 * res.type('application/json');
387 * res.type('png');
388 *
389 * @param {String} type
390 * @return {ServerResponse} for chaining
391 * @api public
392 */
393
3941res.contentType =
395res.type = function(type){
3960 return this.set('Content-Type', ~type.indexOf('/')
397 ? type
398 : mime.lookup(type));
399};
400
401/**
402 * Respond to the Acceptable formats using an `obj`
403 * of mime-type callbacks.
404 *
405 * This method uses `req.accepted`, an array of
406 * acceptable types ordered by their quality values.
407 * When "Accept" is not present the _first_ callback
408 * is invoked, otherwise the first match is used. When
409 * no match is performed the server responds with
410 * 406 "Not Acceptable".
411 *
412 * Content-Type is set for you, however if you choose
413 * you may alter this within the callback using `res.type()`
414 * or `res.set('Content-Type', ...)`.
415 *
416 * res.format({
417 * 'text/plain': function(){
418 * res.send('hey');
419 * },
420 *
421 * 'text/html': function(){
422 * res.send('<p>hey</p>');
423 * },
424 *
425 * 'appliation/json': function(){
426 * res.send({ message: 'hey' });
427 * }
428 * });
429 *
430 * In addition to canonicalized MIME types you may
431 * also use extnames mapped to these types:
432 *
433 * res.format({
434 * text: function(){
435 * res.send('hey');
436 * },
437 *
438 * html: function(){
439 * res.send('<p>hey</p>');
440 * },
441 *
442 * json: function(){
443 * res.send({ message: 'hey' });
444 * }
445 * });
446 *
447 * By default Express passes an `Error`
448 * with a `.status` of 406 to `next(err)`
449 * if a match is not made. If you provide
450 * a `.default` callback it will be invoked
451 * instead.
452 *
453 * @param {Object} obj
454 * @return {ServerResponse} for chaining
455 * @api public
456 */
457
4581res.format = function(obj){
4590 var req = this.req
460 , next = req.next;
461
4620 var fn = obj.default;
4630 if (fn) delete obj.default;
4640 var keys = Object.keys(obj);
465
4660 var key = req.accepts(keys);
467
4680 this.vary("Accept");
469
4700 if (key) {
4710 var type = normalizeType(key).value;
4720 var charset = mime.charsets.lookup(type);
4730 if (charset) type += '; charset=' + charset;
4740 this.set('Content-Type', type);
4750 obj[key](req, this, next);
4760 } else if (fn) {
4770 fn();
478 } else {
4790 var err = new Error('Not Acceptable');
4800 err.status = 406;
4810 err.types = normalizeTypes(keys).map(function(o){ return o.value });
4820 next(err);
483 }
484
4850 return this;
486};
487
488/**
489 * Set _Content-Disposition_ header to _attachment_ with optional `filename`.
490 *
491 * @param {String} filename
492 * @return {ServerResponse}
493 * @api public
494 */
495
4961res.attachment = function(filename){
4970 if (filename) this.type(extname(filename));
4980 this.set('Content-Disposition', filename
499 ? 'attachment; filename="' + basename(filename) + '"'
500 : 'attachment');
5010 return this;
502};
503
504/**
505 * Set header `field` to `val`, or pass
506 * an object of header fields.
507 *
508 * Examples:
509 *
510 * res.set('Foo', ['bar', 'baz']);
511 * res.set('Accept', 'application/json');
512 * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
513 *
514 * Aliased as `res.header()`.
515 *
516 * @param {String|Object|Array} field
517 * @param {String} val
518 * @return {ServerResponse} for chaining
519 * @api public
520 */
521
5221res.set =
523res.header = function(field, val){
5240 if (2 == arguments.length) {
5250 if (Array.isArray(val)) val = val.map(String);
5260 else val = String(val);
5270 this.setHeader(field, val);
528 } else {
5290 for (var key in field) {
5300 this.set(key, field[key]);
531 }
532 }
5330 return this;
534};
535
536/**
537 * Get value for header `field`.
538 *
539 * @param {String} field
540 * @return {String}
541 * @api public
542 */
543
5441res.get = function(field){
5450 return this.getHeader(field);
546};
547
548/**
549 * Clear cookie `name`.
550 *
551 * @param {String} name
552 * @param {Object} options
553 * @param {ServerResponse} for chaining
554 * @api public
555 */
556
5571res.clearCookie = function(name, options){
5580 var opts = { expires: new Date(1), path: '/' };
5590 return this.cookie(name, '', options
560 ? utils.merge(opts, options)
561 : opts);
562};
563
564/**
565 * Set cookie `name` to `val`, with the given `options`.
566 *
567 * Options:
568 *
569 * - `maxAge` max-age in milliseconds, converted to `expires`
570 * - `signed` sign the cookie
571 * - `path` defaults to "/"
572 *
573 * Examples:
574 *
575 * // "Remember Me" for 15 minutes
576 * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
577 *
578 * // save as above
579 * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
580 *
581 * @param {String} name
582 * @param {String|Object} val
583 * @param {Options} options
584 * @api public
585 */
586
5871res.cookie = function(name, val, options){
5880 options = utils.merge({}, options);
5890 var secret = this.req.secret;
5900 var signed = options.signed;
5910 if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies');
5920 if ('number' == typeof val) val = val.toString();
5930 if ('object' == typeof val) val = 'j:' + JSON.stringify(val);
5940 if (signed) val = 's:' + sign(val, secret);
5950 if ('maxAge' in options) {
5960 options.expires = new Date(Date.now() + options.maxAge);
5970 options.maxAge /= 1000;
598 }
5990 if (null == options.path) options.path = '/';
6000 this.set('Set-Cookie', cookie.serialize(name, String(val), options));
6010 return this;
602};
603
604
605/**
606 * Set the location header to `url`.
607 *
608 * The given `url` can also be "back", which redirects
609 * to the _Referrer_ or _Referer_ headers or "/".
610 *
611 * Examples:
612 *
613 * res.location('/foo/bar').;
614 * res.location('http://example.com');
615 * res.location('../login'); // /blog/post/1 -> /blog/login
616 *
617 * Mounting:
618 *
619 * When an application is mounted and `res.location()`
620 * is given a path that does _not_ lead with "/" it becomes
621 * relative to the mount-point. For example if the application
622 * is mounted at "/blog", the following would become "/blog/login".
623 *
624 * res.location('login');
625 *
626 * While the leading slash would result in a location of "/login":
627 *
628 * res.location('/login');
629 *
630 * @param {String} url
631 * @api public
632 */
633
6341res.location = function(url){
6350 var app = this.app
636 , req = this.req
637 , path;
638
639 // "back" is an alias for the referrer
6400 if ('back' == url) url = req.get('Referrer') || '/';
641
642 // relative
6430 if (!~url.indexOf('://') && 0 != url.indexOf('//')) {
644 // relative to path
6450 if ('.' == url[0]) {
6460 path = req.originalUrl.split('?')[0];
6470 path = path + ('/' == path[path.length - 1] ? '' : '/');
6480 url = resolve(path, url);
649 // relative to mount-point
6500 } else if ('/' != url[0]) {
6510 path = app.path();
6520 url = path + '/' + url;
653 }
654 }
655
656 // Respond
6570 this.set('Location', url);
6580 return this;
659};
660
661/**
662 * Redirect to the given `url` with optional response `status`
663 * defaulting to 302.
664 *
665 * The resulting `url` is determined by `res.location()`, so
666 * it will play nicely with mounted apps, relative paths,
667 * `"back"` etc.
668 *
669 * Examples:
670 *
671 * res.redirect('/foo/bar');
672 * res.redirect('http://example.com');
673 * res.redirect(301, 'http://example.com');
674 * res.redirect('http://example.com', 301);
675 * res.redirect('../login'); // /blog/post/1 -> /blog/login
676 *
677 * @param {String} url
678 * @param {Number} code
679 * @api public
680 */
681
6821res.redirect = function(url){
6830 var head = 'HEAD' == this.req.method
684 , status = 302
685 , body;
686
687 // allow status / url
6880 if (2 == arguments.length) {
6890 if ('number' == typeof url) {
6900 status = url;
6910 url = arguments[1];
692 } else {
6930 status = arguments[1];
694 }
695 }
696
697 // Set location header
6980 this.location(url);
6990 url = this.get('Location');
700
701 // Support text/{plain,html} by default
7020 this.format({
703 text: function(){
7040 body = statusCodes[status] + '. Redirecting to ' + encodeURI(url);
705 },
706
707 html: function(){
7080 var u = utils.escape(url);
7090 body = '<p>' + statusCodes[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>';
710 },
711
712 default: function(){
7130 body = '';
714 }
715 });
716
717 // Respond
7180 this.statusCode = status;
7190 this.set('Content-Length', Buffer.byteLength(body));
7200 this.end(head ? null : body);
721};
722
723/**
724 * Add `field` to Vary. If already present in the Vary set, then
725 * this call is simply ignored.
726 *
727 * @param {Array|String} field
728 * @param {ServerResponse} for chaining
729 * @api public
730 */
731
7321res.vary = function(field){
7330 var self = this;
734
735 // nothing
7360 if (!field) return this;
737
738 // array
7390 if (Array.isArray(field)) {
7400 field.forEach(function(field){
7410 self.vary(field);
742 });
7430 return;
744 }
745
7460 var vary = this.get('Vary');
747
748 // append
7490 if (vary) {
7500 vary = vary.split(/ *, */);
7510 if (!~vary.indexOf(field)) vary.push(field);
7520 this.set('Vary', vary.join(', '));
7530 return this;
754 }
755
756 // set
7570 this.set('Vary', field);
7580 return this;
759};
760
761/**
762 * Render `view` with the given `options` and optional callback `fn`.
763 * When a callback function is given a response will _not_ be made
764 * automatically, otherwise a response of _200_ and _text/html_ is given.
765 *
766 * Options:
767 *
768 * - `cache` boolean hinting to the engine it should cache
769 * - `filename` filename of the view being rendered
770 *
771 * @param {String} view
772 * @param {Object|Function} options or callback function
773 * @param {Function} fn
774 * @api public
775 */
776
7771res.render = function(view, options, fn){
7780 var self = this
779 , options = options || {}
780 , req = this.req
781 , app = req.app;
782
783 // support callback function as second arg
7840 if ('function' == typeof options) {
7850 fn = options, options = {};
786 }
787
788 // merge res.locals
7890 options._locals = self.locals;
790
791 // default callback to respond
7920 fn = fn || function(err, str){
7930 if (err) return req.next(err);
7940 self.send(str);
795 };
796
797 // render
7980 app.render(view, options, fn);
799};
800

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/lib/router/index.js

16%
124
21
103
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var Route = require('./route')
6 , utils = require('../utils')
7 , methods = require('methods')
8 , debug = require('debug')('express:router')
9 , parse = require('connect').utils.parseUrl;
10
11/**
12 * Expose `Router` constructor.
13 */
14
151exports = module.exports = Router;
16
17/**
18 * Initialize a new `Router` with the given `options`.
19 *
20 * @param {Object} options
21 * @api private
22 */
23
241function Router(options) {
251 options = options || {};
261 var self = this;
271 this.map = {};
281 this.params = {};
291 this._params = [];
301 this.caseSensitive = options.caseSensitive;
311 this.strict = options.strict;
321 this.middleware = function router(req, res, next){
330 self._dispatch(req, res, next);
34 };
35}
36
37/**
38 * Register a param callback `fn` for the given `name`.
39 *
40 * @param {String|Function} name
41 * @param {Function} fn
42 * @return {Router} for chaining
43 * @api public
44 */
45
461Router.prototype.param = function(name, fn){
47 // param logic
480 if ('function' == typeof name) {
490 this._params.push(name);
500 return;
51 }
52
53 // apply param functions
540 var params = this._params
55 , len = params.length
56 , ret;
57
580 for (var i = 0; i < len; ++i) {
590 if (ret = params[i](name, fn)) {
600 fn = ret;
61 }
62 }
63
64 // ensure we end up with a
65 // middleware function
660 if ('function' != typeof fn) {
670 throw new Error('invalid param() call for ' + name + ', got ' + fn);
68 }
69
700 (this.params[name] = this.params[name] || []).push(fn);
710 return this;
72};
73
74/**
75 * Route dispatcher aka the route "middleware".
76 *
77 * @param {IncomingMessage} req
78 * @param {ServerResponse} res
79 * @param {Function} next
80 * @api private
81 */
82
831Router.prototype._dispatch = function(req, res, next){
840 var params = this.params
85 , self = this;
86
870 debug('dispatching %s %s (%s)', req.method, req.url, req.originalUrl);
88
89 // route dispatch
900 (function pass(i, err){
910 var paramCallbacks
92 , paramIndex = 0
93 , paramVal
94 , route
95 , keys
96 , key;
97
98 // match next route
990 function nextRoute(err) {
1000 pass(req._route_index + 1, err);
101 }
102
103 // match route
1040 req.route = route = self.matchRequest(req, i);
105
106 // implied OPTIONS
1070 if (!route && 'OPTIONS' == req.method) return self._options(req, res, next);
108
109 // no route
1100 if (!route) return next(err);
1110 debug('matched %s %s', route.method, route.path);
112
113 // we have a route
114 // start at param 0
1150 req.params = route.params;
1160 keys = route.keys;
1170 i = 0;
118
119 // param callbacks
1200 function param(err) {
1210 paramIndex = 0;
1220 key = keys[i++];
1230 paramVal = key && req.params[key.name];
1240 paramCallbacks = key && params[key.name];
125
1260 try {
1270 if ('route' == err) {
1280 nextRoute();
1290 } else if (err) {
1300 i = 0;
1310 callbacks(err);
1320 } else if (paramCallbacks && undefined !== paramVal) {
1330 paramCallback();
1340 } else if (key) {
1350 param();
136 } else {
1370 i = 0;
1380 callbacks();
139 }
140 } catch (err) {
1410 param(err);
142 }
143 };
144
1450 param(err);
146
147 // single param callbacks
1480 function paramCallback(err) {
1490 var fn = paramCallbacks[paramIndex++];
1500 if (err || !fn) return param(err);
1510 fn(req, res, paramCallback, paramVal, key.name);
152 }
153
154 // invoke route callbacks
1550 function callbacks(err) {
1560 var fn = route.callbacks[i++];
1570 try {
1580 if ('route' == err) {
1590 nextRoute();
1600 } else if (err && fn) {
1610 if (fn.length < 4) return callbacks(err);
1620 fn(err, req, res, callbacks);
1630 } else if (fn) {
1640 if (fn.length < 4) return fn(req, res, callbacks);
1650 callbacks();
166 } else {
1670 nextRoute(err);
168 }
169 } catch (err) {
1700 callbacks(err);
171 }
172 }
173 })(0);
174};
175
176/**
177 * Respond to __OPTIONS__ method.
178 *
179 * @param {IncomingMessage} req
180 * @param {ServerResponse} res
181 * @api private
182 */
183
1841Router.prototype._options = function(req, res, next){
1850 var path = parse(req).pathname
186 , body = this._optionsFor(path).join(',');
1870 if (!body) return next();
1880 res.set('Allow', body).send(body);
189};
190
191/**
192 * Return an array of HTTP verbs or "options" for `path`.
193 *
194 * @param {String} path
195 * @return {Array}
196 * @api private
197 */
198
1991Router.prototype._optionsFor = function(path){
2000 var self = this;
2010 return methods.filter(function(method){
2020 var routes = self.map[method];
2030 if (!routes || 'options' == method) return;
2040 for (var i = 0, len = routes.length; i < len; ++i) {
2050 if (routes[i].match(path)) return true;
206 }
207 }).map(function(method){
2080 return method.toUpperCase();
209 });
210};
211
212/**
213 * Attempt to match a route for `req`
214 * with optional starting index of `i`
215 * defaulting to 0.
216 *
217 * @param {IncomingMessage} req
218 * @param {Number} i
219 * @return {Route}
220 * @api private
221 */
222
2231Router.prototype.matchRequest = function(req, i, head){
2240 var method = req.method.toLowerCase()
225 , url = parse(req)
226 , path = url.pathname
227 , routes = this.map
228 , i = i || 0
229 , route;
230
231 // HEAD support
2320 if (!head && 'head' == method) {
2330 route = this.matchRequest(req, i, true);
2340 if (route) return route;
2350 method = 'get';
236 }
237
238 // routes for this method
2390 if (routes = routes[method]) {
240
241 // matching routes
2420 for (var len = routes.length; i < len; ++i) {
2430 route = routes[i];
2440 if (route.match(path)) {
2450 req._route_index = i;
2460 return route;
247 }
248 }
249 }
250};
251
252/**
253 * Attempt to match a route for `method`
254 * and `url` with optional starting
255 * index of `i` defaulting to 0.
256 *
257 * @param {String} method
258 * @param {String} url
259 * @param {Number} i
260 * @return {Route}
261 * @api private
262 */
263
2641Router.prototype.match = function(method, url, i, head){
2650 var req = { method: method, url: url };
2660 return this.matchRequest(req, i, head);
267};
268
269/**
270 * Route `method`, `path`, and one or more callbacks.
271 *
272 * @param {String} method
273 * @param {String} path
274 * @param {Function} callback...
275 * @return {Router} for chaining
276 * @api private
277 */
278
2791Router.prototype.route = function(method, path, callbacks){
2800 var method = method.toLowerCase()
281 , callbacks = utils.flatten([].slice.call(arguments, 2));
282
283 // ensure path was given
2840 if (!path) throw new Error('Router#' + method + '() requires a path');
285
286 // ensure all callbacks are functions
2870 callbacks.forEach(function(fn){
2880 if ('function' == typeof fn) return;
2890 var type = {}.toString.call(fn);
2900 var msg = '.' + method + '() requires callback functions but got a ' + type;
2910 throw new Error(msg);
292 });
293
294 // create the route
2950 debug('defined %s %s', method, path);
2960 var route = new Route(method, path, callbacks, {
297 sensitive: this.caseSensitive,
298 strict: this.strict
299 });
300
301 // add it
3020 (this.map[method] = this.map[method] || []).push(route);
3030 return this;
304};
305
3061Router.prototype.all = function(path) {
3070 var self = this;
3080 var args = [].slice.call(arguments);
3090 methods.forEach(function(method){
3100 self.route.apply(self, [method].concat(args));
311 });
3120 return this;
313};
314
3151methods.forEach(function(method){
31624 Router.prototype[method] = function(path){
3170 var args = [method].concat([].slice.call(arguments));
3180 this.route.apply(this, args);
3190 return this;
320 };
321});
322

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/lib/router/route.js

18%
22
4
18
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var utils = require('../utils');
7
8/**
9 * Expose `Route`.
10 */
11
121module.exports = Route;
13
14/**
15 * Initialize `Route` with the given HTTP `method`, `path`,
16 * and an array of `callbacks` and `options`.
17 *
18 * Options:
19 *
20 * - `sensitive` enable case-sensitive routes
21 * - `strict` enable strict matching for trailing slashes
22 *
23 * @param {String} method
24 * @param {String} path
25 * @param {Array} callbacks
26 * @param {Object} options.
27 * @api private
28 */
29
301function Route(method, path, callbacks, options) {
310 options = options || {};
320 this.path = path;
330 this.method = method;
340 this.callbacks = callbacks;
350 this.regexp = utils.pathRegexp(path
36 , this.keys = []
37 , options.sensitive
38 , options.strict);
39}
40
41/**
42 * Check if this route matches `path`, if so
43 * populate `.params`.
44 *
45 * @param {String} path
46 * @return {Boolean}
47 * @api private
48 */
49
501Route.prototype.match = function(path){
510 var keys = this.keys
52 , params = this.params = []
53 , m = this.regexp.exec(path);
54
550 if (!m) return false;
56
570 for (var i = 1, len = m.length; i < len; ++i) {
580 var key = keys[i - 1];
59
600 try {
610 var val = 'string' == typeof m[i]
62 ? decodeURIComponent(m[i])
63 : m[i];
64 } catch(e) {
650 var err = new Error("Failed to decode param '" + m[i] + "'");
660 err.status = 400;
670 throw err;
68 }
69
700 if (key) {
710 params[key.name] = val;
72 } else {
730 params.push(val);
74 }
75 }
76
770 return true;
78};
79

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/lib/utils.js

25%
74
19
55
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var mime = require('connect').mime
7 , crc32 = require('buffer-crc32');
8
9/**
10 * toString ref.
11 */
12
131var toString = {}.toString;
14
15/**
16 * Return ETag for `body`.
17 *
18 * @param {String|Buffer} body
19 * @return {String}
20 * @api private
21 */
22
231exports.etag = function(body){
240 return '"' + crc32.signed(body) + '"';
25};
26
27/**
28 * Make `locals()` bound to the given `obj`.
29 *
30 * This is used for `app.locals` and `res.locals`.
31 *
32 * @param {Object} obj
33 * @return {Function}
34 * @api private
35 */
36
371exports.locals = function(){
381 function locals(obj){
390 for (var key in obj) locals[key] = obj[key];
400 return obj;
41 };
42
431 return locals;
44};
45
46/**
47 * Check if `path` looks absolute.
48 *
49 * @param {String} path
50 * @return {Boolean}
51 * @api private
52 */
53
541exports.isAbsolute = function(path){
550 if ('/' == path[0]) return true;
560 if (':' == path[1] && '\\' == path[2]) return true;
570 if ('\\\\' == path.substring(0, 2)) return true; // Microsoft Azure absolute path
58};
59
60/**
61 * Flatten the given `arr`.
62 *
63 * @param {Array} arr
64 * @return {Array}
65 * @api private
66 */
67
681exports.flatten = function(arr, ret){
690 var ret = ret || []
70 , len = arr.length;
710 for (var i = 0; i < len; ++i) {
720 if (Array.isArray(arr[i])) {
730 exports.flatten(arr[i], ret);
74 } else {
750 ret.push(arr[i]);
76 }
77 }
780 return ret;
79};
80
81/**
82 * Normalize the given `type`, for example "html" becomes "text/html".
83 *
84 * @param {String} type
85 * @return {Object}
86 * @api private
87 */
88
891exports.normalizeType = function(type){
900 return ~type.indexOf('/')
91 ? acceptParams(type)
92 : { value: mime.lookup(type), params: {} };
93};
94
95/**
96 * Normalize `types`, for example "html" becomes "text/html".
97 *
98 * @param {Array} types
99 * @return {Array}
100 * @api private
101 */
102
1031exports.normalizeTypes = function(types){
1040 var ret = [];
105
1060 for (var i = 0; i < types.length; ++i) {
1070 ret.push(exports.normalizeType(types[i]));
108 }
109
1100 return ret;
111};
112
113/**
114 * Return the acceptable type in `types`, if any.
115 *
116 * @param {Array} types
117 * @param {String} str
118 * @return {String}
119 * @api private
120 */
121
1221exports.acceptsArray = function(types, str){
123 // accept anything when Accept is not present
1240 if (!str) return types[0];
125
126 // parse
1270 var accepted = exports.parseAccept(str)
128 , normalized = exports.normalizeTypes(types)
129 , len = accepted.length;
130
1310 for (var i = 0; i < len; ++i) {
1320 for (var j = 0, jlen = types.length; j < jlen; ++j) {
1330 if (exports.accept(normalized[j], accepted[i])) {
1340 return types[j];
135 }
136 }
137 }
138};
139
140/**
141 * Check if `type(s)` are acceptable based on
142 * the given `str`.
143 *
144 * @param {String|Array} type(s)
145 * @param {String} str
146 * @return {Boolean|String}
147 * @api private
148 */
149
1501exports.accepts = function(type, str){
1510 if ('string' == typeof type) type = type.split(/ *, */);
1520 return exports.acceptsArray(type, str);
153};
154
155/**
156 * Check if `type` array is acceptable for `other`.
157 *
158 * @param {Object} type
159 * @param {Object} other
160 * @return {Boolean}
161 * @api private
162 */
163
1641exports.accept = function(type, other){
1650 var t = type.value.split('/');
1660 return (t[0] == other.type || '*' == other.type)
167 && (t[1] == other.subtype || '*' == other.subtype)
168 && paramsEqual(type.params, other.params);
169};
170
171/**
172 * Check if accept params are equal.
173 *
174 * @param {Object} a
175 * @param {Object} b
176 * @return {Boolean}
177 * @api private
178 */
179
1801function paramsEqual(a, b){
1810 return !Object.keys(a).some(function(k) {
1820 return a[k] != b[k];
183 });
184}
185
186/**
187 * Parse accept `str`, returning
188 * an array objects containing
189 * `.type` and `.subtype` along
190 * with the values provided by
191 * `parseQuality()`.
192 *
193 * @param {Type} name
194 * @return {Type}
195 * @api private
196 */
197
1981exports.parseAccept = function(str){
1990 return exports
200 .parseParams(str)
201 .map(function(obj){
2020 var parts = obj.value.split('/');
2030 obj.type = parts[0];
2040 obj.subtype = parts[1];
2050 return obj;
206 });
207};
208
209/**
210 * Parse quality `str`, returning an
211 * array of objects with `.value`,
212 * `.quality` and optional `.params`
213 *
214 * @param {String} str
215 * @return {Array}
216 * @api private
217 */
218
2191exports.parseParams = function(str){
2200 return str
221 .split(/ *, */)
222 .map(acceptParams)
223 .filter(function(obj){
2240 return obj.quality;
225 })
226 .sort(function(a, b){
2270 if (a.quality === b.quality) {
2280 return a.originalIndex - b.originalIndex;
229 } else {
2300 return b.quality - a.quality;
231 }
232 });
233};
234
235/**
236 * Parse accept params `str` returning an
237 * object with `.value`, `.quality` and `.params`.
238 * also includes `.originalIndex` for stable sorting
239 *
240 * @param {String} str
241 * @return {Object}
242 * @api private
243 */
244
2451function acceptParams(str, index) {
2460 var parts = str.split(/ *; */);
2470 var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
248
2490 for (var i = 1; i < parts.length; ++i) {
2500 var pms = parts[i].split(/ *= */);
2510 if ('q' == pms[0]) {
2520 ret.quality = parseFloat(pms[1]);
253 } else {
2540 ret.params[pms[0]] = pms[1];
255 }
256 }
257
2580 return ret;
259}
260
261/**
262 * Escape special characters in the given string of html.
263 *
264 * @param {String} html
265 * @return {String}
266 * @api private
267 */
268
2691exports.escape = function(html) {
2700 return String(html)
271 .replace(/&/g, '&')
272 .replace(/"/g, '"')
273 .replace(/</g, '<')
274 .replace(/>/g, '>');
275};
276
277/**
278 * Normalize the given path string,
279 * returning a regular expression.
280 *
281 * An empty array should be passed,
282 * which will contain the placeholder
283 * key names. For example "/user/:id" will
284 * then contain ["id"].
285 *
286 * @param {String|RegExp|Array} path
287 * @param {Array} keys
288 * @param {Boolean} sensitive
289 * @param {Boolean} strict
290 * @return {RegExp}
291 * @api private
292 */
293
2941exports.pathRegexp = function(path, keys, sensitive, strict) {
2950 if (toString.call(path) == '[object RegExp]') return path;
2960 if (Array.isArray(path)) path = '(' + path.join('|') + ')';
2970 path = path
298 .concat(strict ? '' : '/?')
299 .replace(/\/\(/g, '(?:/')
300 .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function(_, slash, format, key, capture, optional, star){
3010 keys.push({ name: key, optional: !! optional });
3020 slash = slash || '';
3030 return ''
304 + (optional ? '' : slash)
305 + '(?:'
306 + (optional ? slash : '')
307 + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')'
308 + (optional || '')
309 + (star ? '(/*)?' : '');
310 })
311 .replace(/([\/.])/g, '\\$1')
312 .replace(/\*/g, '(.*)');
3130 return new RegExp('^' + path + '$', sensitive ? '' : 'i');
314}
315

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/lib/view.js

23%
21
5
16
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var path = require('path')
6 , fs = require('fs')
7 , utils = require('./utils')
8 , dirname = path.dirname
9 , basename = path.basename
10 , extname = path.extname
11 , exists = fs.existsSync || path.existsSync
12 , join = path.join;
13
14/**
15 * Expose `View`.
16 */
17
181module.exports = View;
19
20/**
21 * Initialize a new `View` with the given `name`.
22 *
23 * Options:
24 *
25 * - `defaultEngine` the default template engine name
26 * - `engines` template engine require() cache
27 * - `root` root path for view lookup
28 *
29 * @param {String} name
30 * @param {Object} options
31 * @api private
32 */
33
341function View(name, options) {
350 options = options || {};
360 this.name = name;
370 this.root = options.root;
380 var engines = options.engines;
390 this.defaultEngine = options.defaultEngine;
400 var ext = this.ext = extname(name);
410 if (!ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.');
420 if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine);
430 this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express);
440 this.path = this.lookup(name);
45}
46
47/**
48 * Lookup view by the given `path`
49 *
50 * @param {String} path
51 * @return {String}
52 * @api private
53 */
54
551View.prototype.lookup = function(path){
560 var ext = this.ext;
57
58 // <path>.<engine>
590 if (!utils.isAbsolute(path)) path = join(this.root, path);
600 if (exists(path)) return path;
61
62 // <path>/index.<engine>
630 path = join(dirname(path), basename(path, ext), 'index' + ext);
640 if (exists(path)) return path;
65};
66
67/**
68 * Render with the given `options` and callback `fn(err, str)`.
69 *
70 * @param {Object} options
71 * @param {Function} fn
72 * @api private
73 */
74
751View.prototype.render = function(options, fn){
760 this.engine(this.path, options, fn);
77};
78

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/node_modules/connect/lib/connect.js

95%
24
23
1
LineHitsSource
1/*!
2 * Connect
3 * Copyright(c) 2010 Sencha Inc.
4 * Copyright(c) 2011 TJ Holowaychuk
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var EventEmitter = require('events').EventEmitter
13 , proto = require('./proto')
14 , utils = require('./utils')
15 , path = require('path')
16 , basename = path.basename
17 , fs = require('fs');
18
19// node patches
20
211require('./patch');
22
23// expose createServer() as the module
24
251exports = module.exports = createServer;
26
27/**
28 * Framework version.
29 */
30
311exports.version = '2.7.11';
32
33/**
34 * Expose mime module.
35 */
36
371exports.mime = require('./middleware/static').mime;
38
39/**
40 * Expose the prototype.
41 */
42
431exports.proto = proto;
44
45/**
46 * Auto-load middleware getters.
47 */
48
491exports.middleware = {};
50
51/**
52 * Expose utilities.
53 */
54
551exports.utils = utils;
56
57/**
58 * Create a new connect server.
59 *
60 * @return {Function}
61 * @api public
62 */
63
641function createServer() {
651 function app(req, res, next){ app.handle(req, res, next); }
661 utils.merge(app, proto);
671 utils.merge(app, EventEmitter.prototype);
681 app.route = '/';
691 app.stack = [];
701 for (var i = 0; i < arguments.length; ++i) {
710 app.use(arguments[i]);
72 }
731 return app;
74};
75
76/**
77 * Support old `.createServer()` method.
78 */
79
801createServer.createServer = createServer;
81
82/**
83 * Auto-load bundled middleware with getters.
84 */
85
861fs.readdirSync(__dirname + '/middleware').forEach(function(filename){
8724 if (!/\.js$/.test(filename)) return;
8822 var name = basename(filename, '.js');
8924 function load(){ return require('./middleware/' + name); }
9022 exports.middleware.__defineGetter__(name, load);
9122 exports.__defineGetter__(name, load);
92});
93

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js

16%
25
4
21
LineHitsSource
1/*!
2 * Connect - errorHandler
3 * Copyright(c) 2010 Sencha Inc.
4 * Copyright(c) 2011 TJ Holowaychuk
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var utils = require('../utils')
13 , fs = require('fs');
14
15// environment
16
171var env = process.env.NODE_ENV || 'development';
18
19/**
20 * Error handler:
21 *
22 * Development error handler, providing stack traces
23 * and error message responses for requests accepting text, html,
24 * or json.
25 *
26 * Text:
27 *
28 * By default, and when _text/plain_ is accepted a simple stack trace
29 * or error message will be returned.
30 *
31 * JSON:
32 *
33 * When _application/json_ is accepted, connect will respond with
34 * an object in the form of `{ "error": error }`.
35 *
36 * HTML:
37 *
38 * When accepted connect will output a nice html stack trace.
39 *
40 * @return {Function}
41 * @api public
42 */
43
441exports = module.exports = function errorHandler(){
450 return function errorHandler(err, req, res, next){
460 if (err.status) res.statusCode = err.status;
470 if (res.statusCode < 400) res.statusCode = 500;
480 if ('test' != env) console.error(err.stack);
490 var accept = req.headers.accept || '';
50 // html
510 if (~accept.indexOf('html')) {
520 fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){
530 fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){
540 var stack = (err.stack || '')
55 .split('\n').slice(1)
560 .map(function(v){ return '<li>' + v + '</li>'; }).join('');
570 html = html
58 .replace('{style}', style)
59 .replace('{stack}', stack)
60 .replace('{title}', exports.title)
61 .replace('{statusCode}', res.statusCode)
62 .replace(/\{error\}/g, utils.escape(err.toString().replace(/\n/g, '<br/>')));
630 res.setHeader('Content-Type', 'text/html; charset=utf-8');
640 res.end(html);
65 });
66 });
67 // json
680 } else if (~accept.indexOf('json')) {
690 var error = { message: err.message, stack: err.stack };
700 for (var prop in err) error[prop] = err[prop];
710 var json = JSON.stringify({ error: error });
720 res.setHeader('Content-Type', 'application/json');
730 res.end(json);
74 // plain text
75 } else {
760 res.setHeader('Content-Type', 'text/plain');
770 res.end(err.stack);
78 }
79 };
80};
81
82/**
83 * Template title, framework authors may override this value.
84 */
85
861exports.title = 'Connect';
87

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/node_modules/connect/lib/middleware/query.js

50%
6
3
3
LineHitsSource
1/*!
2 * Connect - query
3 * Copyright(c) 2011 TJ Holowaychuk
4 * Copyright(c) 2011 Sencha Inc.
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var qs = require('qs')
13 , parse = require('../utils').parseUrl;
14
15/**
16 * Query:
17 *
18 * Automatically parse the query-string when available,
19 * populating the `req.query` object using
20 * [qs](https://github.com/visionmedia/node-querystring).
21 *
22 * Examples:
23 *
24 * connect()
25 * .use(connect.query())
26 * .use(function(req, res){
27 * res.end(JSON.stringify(req.query));
28 * });
29 *
30 * The `options` passed are provided to qs.parse function.
31 *
32 * @param {Object} options
33 * @return {Function}
34 * @api public
35 */
36
371module.exports = function query(options){
381 return function query(req, res, next){
390 if (!req.query) {
400 req.query = ~req.url.indexOf('?')
41 ? qs.parse(parse(req).query, options)
42 : {};
43 }
44
450 next();
46 };
47};
48

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/node_modules/connect/lib/middleware/static.js

10%
28
3
25
LineHitsSource
1/*!
2 * Connect - static
3 * Copyright(c) 2010 Sencha Inc.
4 * Copyright(c) 2011 TJ Holowaychuk
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var send = require('send')
13 , utils = require('../utils')
14 , parse = utils.parseUrl
15 , url = require('url');
16
17/**
18 * Static:
19 *
20 * Static file server with the given `root` path.
21 *
22 * Examples:
23 *
24 * var oneDay = 86400000;
25 *
26 * connect()
27 * .use(connect.static(__dirname + '/public'))
28 *
29 * connect()
30 * .use(connect.static(__dirname + '/public', { maxAge: oneDay }))
31 *
32 * Options:
33 *
34 * - `maxAge` Browser cache maxAge in milliseconds. defaults to 0
35 * - `hidden` Allow transfer of hidden files. defaults to false
36 * - `redirect` Redirect to trailing "/" when the pathname is a dir. defaults to true
37 * - `index` Default file name, defaults to 'index.html'
38 *
39 * @param {String} root
40 * @param {Object} options
41 * @return {Function}
42 * @api public
43 */
44
451exports = module.exports = function(root, options){
460 options = options || {};
47
48 // root required
490 if (!root) throw new Error('static() root path required');
50
51 // default redirect
520 var redirect = false !== options.redirect;
53
540 return function staticMiddleware(req, res, next) {
550 if ('GET' != req.method && 'HEAD' != req.method) return next();
560 var originalUrl = url.parse(req.originalUrl);
570 var path = parse(req).pathname;
580 var pause = utils.pause(req);
59
600 if (path == '/' && originalUrl.pathname[originalUrl.pathname.length - 1] != '/') {
610 return directory();
62 }
63
640 function resume() {
650 next();
660 pause.resume();
67 }
68
690 function directory() {
700 if (!redirect) return resume();
710 var target;
720 originalUrl.pathname += '/';
730 target = url.format(originalUrl);
740 res.statusCode = 303;
750 res.setHeader('Location', target);
760 res.end('Redirecting to ' + utils.escape(target));
77 }
78
790 function error(err) {
800 if (404 == err.status) return resume();
810 next(err);
82 }
83
840 send(req, path)
85 .maxage(options.maxAge || 0)
86 .root(root)
87 .index(options.index || 'index.html')
88 .hidden(options.hidden)
89 .on('error', error)
90 .on('directory', directory)
91 .pipe(res);
92 };
93};
94
95/**
96 * Expose mime module.
97 *
98 * If you wish to extend the mime table use this
99 * reference to the "mime" module in the npm registry.
100 */
101
1021exports.mime = send.mime;
103

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/node_modules/connect/lib/patch.js

24%
29
7
22
LineHitsSource
1
2/*!
3 * Connect
4 * Copyright(c) 2011 TJ Holowaychuk
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var http = require('http')
13 , res = http.ServerResponse.prototype
14 , setHeader = res.setHeader
15 , _renderHeaders = res._renderHeaders
16 , writeHead = res.writeHead;
17
18// apply only once
19
201if (!res._hasConnectPatch) {
21
22 /**
23 * Provide a public "header sent" flag
24 * until node does.
25 *
26 * @return {Boolean}
27 * @api public
28 */
29
301 res.__defineGetter__('headerSent', function(){
310 return this._header;
32 });
33
34 /**
35 * Set header `field` to `val`, special-casing
36 * the `Set-Cookie` field for multiple support.
37 *
38 * @param {String} field
39 * @param {String} val
40 * @api public
41 */
42
431 res.setHeader = function(field, val){
440 var key = field.toLowerCase()
45 , prev;
46
47 // special-case Set-Cookie
480 if (this._headers && 'set-cookie' == key) {
490 if (prev = this.getHeader(field)) {
500 if (Array.isArray(prev)) {
510 val = prev.concat(val);
520 } else if (Array.isArray(val)) {
530 val = val.concat(prev);
54 } else {
550 val = [prev, val];
56 }
57 }
58 // charset
590 } else if ('content-type' == key && this.charset) {
600 val += '; charset=' + this.charset;
61 }
62
630 return setHeader.call(this, field, val);
64 };
65
66 /**
67 * Proxy to emit "header" event.
68 */
69
701 res._renderHeaders = function(){
710 if (!this._emittedHeader) this.emit('header');
720 this._emittedHeader = true;
730 return _renderHeaders.call(this);
74 };
75
761 res.writeHead = function(statusCode, reasonPhrase, headers){
770 if (typeof reasonPhrase === 'object') headers = reasonPhrase;
780 if (typeof headers === 'object') {
790 Object.keys(headers).forEach(function(key){
800 this.setHeader(key, headers[key]);
81 }, this);
82 }
830 if (!this._emittedHeader) this.emit('header');
840 this._emittedHeader = true;
850 return writeHead.call(this, statusCode, reasonPhrase);
86 };
87
881 res._hasConnectPatch = true;
89}
90

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/node_modules/connect/lib/proto.js

18%
75
14
61
LineHitsSource
1/*!
2 * Connect - HTTPServer
3 * Copyright(c) 2010 Sencha Inc.
4 * Copyright(c) 2011 TJ Holowaychuk
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var http = require('http')
13 , utils = require('./utils')
14 , debug = require('debug')('connect:dispatcher');
15
16// prototype
17
181var app = module.exports = {};
19
20// environment
21
221var env = process.env.NODE_ENV || 'development';
23
24/**
25 * Utilize the given middleware `handle` to the given `route`,
26 * defaulting to _/_. This "route" is the mount-point for the
27 * middleware, when given a value other than _/_ the middleware
28 * is only effective when that segment is present in the request's
29 * pathname.
30 *
31 * For example if we were to mount a function at _/admin_, it would
32 * be invoked on _/admin_, and _/admin/settings_, however it would
33 * not be invoked for _/_, or _/posts_.
34 *
35 * Examples:
36 *
37 * var app = connect();
38 * app.use(connect.favicon());
39 * app.use(connect.logger());
40 * app.use(connect.static(__dirname + '/public'));
41 *
42 * If we wanted to prefix static files with _/public_, we could
43 * "mount" the `static()` middleware:
44 *
45 * app.use('/public', connect.static(__dirname + '/public'));
46 *
47 * This api is chainable, so the following is valid:
48 *
49 * connect()
50 * .use(connect.favicon())
51 * .use(connect.logger())
52 * .use(connect.static(__dirname + '/public'))
53 * .listen(3000);
54 *
55 * @param {String|Function|Server} route, callback or server
56 * @param {Function|Server} callback or server
57 * @return {Server} for chaining
58 * @api public
59 */
60
611app.use = function(route, fn){
62 // default route to '/'
632 if ('string' != typeof route) {
640 fn = route;
650 route = '/';
66 }
67
68 // wrap sub-apps
692 if ('function' == typeof fn.handle) {
700 var server = fn;
710 fn.route = route;
720 fn = function(req, res, next){
730 server.handle(req, res, next);
74 };
75 }
76
77 // wrap vanilla http.Servers
782 if (fn instanceof http.Server) {
790 fn = fn.listeners('request')[0];
80 }
81
82 // strip trailing slash
832 if ('/' == route[route.length - 1]) {
842 route = route.slice(0, -1);
85 }
86
87 // add the middleware
882 debug('use %s %s', route || '/', fn.name || 'anonymous');
892 this.stack.push({ route: route, handle: fn });
90
912 return this;
92};
93
94/**
95 * Handle server requests, punting them down
96 * the middleware stack.
97 *
98 * @api private
99 */
100
1011app.handle = function(req, res, out) {
1020 var stack = this.stack
103 , search = 1 + req.url.indexOf('?')
104 , pathlength = search ? search - 1 : req.url.length
105 , fqdn = 1 + req.url.substr(0, pathlength).indexOf('://')
106 , protohost = fqdn ? req.url.substr(0, req.url.indexOf('/', 2 + fqdn)) : ''
107 , removed = ''
108 , slashAdded = false
109 , index = 0;
110
1110 function next(err) {
1120 var layer, path, c;
113
1140 if (slashAdded) {
1150 req.url = req.url.substr(1);
1160 slashAdded = false;
117 }
118
1190 req.url = protohost + removed + req.url.substr(protohost.length);
1200 req.originalUrl = req.originalUrl || req.url;
1210 removed = '';
122
123 // next callback
1240 layer = stack[index++];
125
126 // all done
1270 if (!layer || res.headerSent) {
128 // delegate to parent
1290 if (out) return out(err);
130
131 // unhandled error
1320 if (err) {
133 // default to 500
1340 if (res.statusCode < 400) res.statusCode = 500;
1350 debug('default %s', res.statusCode);
136
137 // respect err.status
1380 if (err.status) res.statusCode = err.status;
139
140 // production gets a basic error message
1410 var msg = 'production' == env
142 ? http.STATUS_CODES[res.statusCode]
143 : err.stack || err.toString();
1440 msg = utils.escape(msg);
145
146 // log to stderr in a non-test env
1470 if ('test' != env) console.error(err.stack || err.toString());
1480 if (res.headerSent) return req.socket.destroy();
1490 res.setHeader('Content-Type', 'text/html');
1500 res.setHeader('Content-Length', Buffer.byteLength(msg));
1510 if ('HEAD' == req.method) return res.end();
1520 res.end(msg);
153 } else {
1540 debug('default 404');
1550 res.statusCode = 404;
1560 res.setHeader('Content-Type', 'text/html');
1570 if ('HEAD' == req.method) return res.end();
1580 res.end('Cannot ' + utils.escape(req.method) + ' ' + utils.escape(req.originalUrl) + '\n');
159 }
1600 return;
161 }
162
1630 try {
1640 path = utils.parseUrl(req).pathname;
1650 if (undefined == path) path = '/';
166
167 // skip this layer if the route doesn't match.
1680 if (0 != path.toLowerCase().indexOf(layer.route.toLowerCase())) return next(err);
169
1700 c = path[layer.route.length];
1710 if (c && '/' != c && '.' != c) return next(err);
172
173 // Call the layer handler
174 // Trim off the part of the url that matches the route
1750 removed = layer.route;
1760 req.url = protohost + req.url.substr(protohost.length + removed.length);
177
178 // Ensure leading slash
1790 if (!fqdn && '/' != req.url[0]) {
1800 req.url = '/' + req.url;
1810 slashAdded = true;
182 }
183
1840 debug('%s %s : %s', layer.handle.name || 'anonymous', layer.route, req.originalUrl);
1850 var arity = layer.handle.length;
1860 if (err) {
1870 if (arity === 4) {
1880 layer.handle(err, req, res, next);
189 } else {
1900 next(err);
191 }
1920 } else if (arity < 4) {
1930 layer.handle(req, res, next);
194 } else {
1950 next();
196 }
197 } catch (e) {
1980 next(e);
199 }
200 }
2010 next();
202};
203
204/**
205 * Listen for connections.
206 *
207 * This method takes the same arguments
208 * as node's `http.Server#listen()`.
209 *
210 * HTTP and HTTPS:
211 *
212 * If you run your application both as HTTP
213 * and HTTPS you may wrap them individually,
214 * since your Connect "server" is really just
215 * a JavaScript `Function`.
216 *
217 * var connect = require('connect')
218 * , http = require('http')
219 * , https = require('https');
220 *
221 * var app = connect();
222 *
223 * http.createServer(app).listen(80);
224 * https.createServer(options, app).listen(443);
225 *
226 * @return {http.Server}
227 * @api public
228 */
229
2301app.listen = function(){
2310 var server = http.createServer(this);
2320 return server.listen.apply(server, arguments);
233};
234

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/node_modules/connect/lib/utils.js

32%
88
29
59
LineHitsSource
1
2/*!
3 * Connect - utils
4 * Copyright(c) 2010 Sencha Inc.
5 * Copyright(c) 2011 TJ Holowaychuk
6 * MIT Licensed
7 */
8
9/**
10 * Module dependencies.
11 */
12
131var http = require('http')
14 , crypto = require('crypto')
15 , parse = require('url').parse
16 , sep = require('path').sep
17 , signature = require('cookie-signature')
18 , nodeVersion = process.versions.node.split('.');
19
20// pause is broken in node < 0.10
211exports.brokenPause = parseInt(nodeVersion[0], 10) === 0
22 && parseInt(nodeVersion[1], 10) < 10;
23
24/**
25 * Return `true` if the request has a body, otherwise return `false`.
26 *
27 * @param {IncomingMessage} req
28 * @return {Boolean}
29 * @api private
30 */
31
321exports.hasBody = function(req) {
330 var encoding = 'transfer-encoding' in req.headers;
340 var length = 'content-length' in req.headers && req.headers['content-length'] !== '0';
350 return encoding || length;
36};
37
38/**
39 * Extract the mime type from the given request's
40 * _Content-Type_ header.
41 *
42 * @param {IncomingMessage} req
43 * @return {String}
44 * @api private
45 */
46
471exports.mime = function(req) {
480 var str = req.headers['content-type'] || '';
490 return str.split(';')[0];
50};
51
52/**
53 * Generate an `Error` from the given status `code`
54 * and optional `msg`.
55 *
56 * @param {Number} code
57 * @param {String} msg
58 * @return {Error}
59 * @api private
60 */
61
621exports.error = function(code, msg){
630 var err = new Error(msg || http.STATUS_CODES[code]);
640 err.status = code;
650 return err;
66};
67
68/**
69 * Return md5 hash of the given string and optional encoding,
70 * defaulting to hex.
71 *
72 * utils.md5('wahoo');
73 * // => "e493298061761236c96b02ea6aa8a2ad"
74 *
75 * @param {String} str
76 * @param {String} encoding
77 * @return {String}
78 * @api private
79 */
80
811exports.md5 = function(str, encoding){
820 return crypto
83 .createHash('md5')
84 .update(str, 'utf8')
85 .digest(encoding || 'hex');
86};
87
88/**
89 * Merge object b with object a.
90 *
91 * var a = { foo: 'bar' }
92 * , b = { bar: 'baz' };
93 *
94 * utils.merge(a, b);
95 * // => { foo: 'bar', bar: 'baz' }
96 *
97 * @param {Object} a
98 * @param {Object} b
99 * @return {Object}
100 * @api private
101 */
102
1031exports.merge = function(a, b){
1043 if (a && b) {
1053 for (var key in b) {
10651 a[key] = b[key];
107 }
108 }
1093 return a;
110};
111
112/**
113 * Escape the given string of `html`.
114 *
115 * @param {String} html
116 * @return {String}
117 * @api private
118 */
119
1201exports.escape = function(html){
1210 return String(html)
122 .replace(/&(?!\w+;)/g, '&')
123 .replace(/</g, '<')
124 .replace(/>/g, '>')
125 .replace(/"/g, '"');
126};
127
128/**
129 * Sign the given `val` with `secret`.
130 *
131 * @param {String} val
132 * @param {String} secret
133 * @return {String}
134 * @api private
135 */
136
1371exports.sign = function(val, secret){
1380 console.warn('do not use utils.sign(), use https://github.com/visionmedia/node-cookie-signature')
1390 return val + '.' + crypto
140 .createHmac('sha256', secret)
141 .update(val)
142 .digest('base64')
143 .replace(/=+$/, '');
144};
145
146/**
147 * Unsign and decode the given `val` with `secret`,
148 * returning `false` if the signature is invalid.
149 *
150 * @param {String} val
151 * @param {String} secret
152 * @return {String|Boolean}
153 * @api private
154 */
155
1561exports.unsign = function(val, secret){
1570 console.warn('do not use utils.unsign(), use https://github.com/visionmedia/node-cookie-signature')
1580 var str = val.slice(0, val.lastIndexOf('.'));
1590 return exports.sign(str, secret) == val
160 ? str
161 : false;
162};
163
164/**
165 * Parse signed cookies, returning an object
166 * containing the decoded key/value pairs,
167 * while removing the signed key from `obj`.
168 *
169 * @param {Object} obj
170 * @return {Object}
171 * @api private
172 */
173
1741exports.parseSignedCookies = function(obj, secret){
1750 var ret = {};
1760 Object.keys(obj).forEach(function(key){
1770 var val = obj[key];
1780 if (0 == val.indexOf('s:')) {
1790 val = signature.unsign(val.slice(2), secret);
1800 if (val) {
1810 ret[key] = val;
1820 delete obj[key];
183 }
184 }
185 });
1860 return ret;
187};
188
189/**
190 * Parse a signed cookie string, return the decoded value
191 *
192 * @param {String} str signed cookie string
193 * @param {String} secret
194 * @return {String} decoded value
195 * @api private
196 */
197
1981exports.parseSignedCookie = function(str, secret){
1990 return 0 == str.indexOf('s:')
200 ? signature.unsign(str.slice(2), secret)
201 : str;
202};
203
204/**
205 * Parse JSON cookies.
206 *
207 * @param {Object} obj
208 * @return {Object}
209 * @api private
210 */
211
2121exports.parseJSONCookies = function(obj){
2130 Object.keys(obj).forEach(function(key){
2140 var val = obj[key];
2150 var res = exports.parseJSONCookie(val);
2160 if (res) obj[key] = res;
217 });
2180 return obj;
219};
220
221/**
222 * Parse JSON cookie string
223 *
224 * @param {String} str
225 * @return {Object} Parsed object or null if not json cookie
226 * @api private
227 */
228
2291exports.parseJSONCookie = function(str) {
2300 if (0 == str.indexOf('j:')) {
2310 try {
2320 return JSON.parse(str.slice(2));
233 } catch (err) {
234 // no op
235 }
236 }
237};
238
239/**
240 * Pause `data` and `end` events on the given `obj`.
241 * Middleware performing async tasks _should_ utilize
242 * this utility (or similar), to re-emit data once
243 * the async operation has completed, otherwise these
244 * events may be lost. Pause is only required for
245 * node versions less than 10, and is replaced with
246 * noop's otherwise.
247 *
248 * var pause = utils.pause(req);
249 * fs.readFile(path, function(){
250 * next();
251 * pause.resume();
252 * });
253 *
254 * @param {Object} obj
255 * @return {Object}
256 * @api private
257 */
258
2591exports.pause = exports.brokenPause
260 ? require('pause')
261 : function () {
2620 return {
263 end: noop,
264 resume: noop
265 }
266 }
267
268/**
269 * Strip `Content-*` headers from `res`.
270 *
271 * @param {ServerResponse} res
272 * @api private
273 */
274
2751exports.removeContentHeaders = function(res){
2760 if (!res._headers) return;
2770 Object.keys(res._headers).forEach(function(field){
2780 if (0 == field.indexOf('content')) {
2790 res.removeHeader(field);
280 }
281 });
282};
283
284/**
285 * Check if `req` is a conditional GET request.
286 *
287 * @param {IncomingMessage} req
288 * @return {Boolean}
289 * @api private
290 */
291
2921exports.conditionalGET = function(req) {
2930 return req.headers['if-modified-since']
294 || req.headers['if-none-match'];
295};
296
297/**
298 * Respond with 401 "Unauthorized".
299 *
300 * @param {ServerResponse} res
301 * @param {String} realm
302 * @api private
303 */
304
3051exports.unauthorized = function(res, realm) {
3060 res.statusCode = 401;
3070 res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"');
3080 res.end('Unauthorized');
309};
310
311/**
312 * Respond with 304 "Not Modified".
313 *
314 * @param {ServerResponse} res
315 * @param {Object} headers
316 * @api private
317 */
318
3191exports.notModified = function(res) {
3200 exports.removeContentHeaders(res);
3210 res.statusCode = 304;
3220 res.end();
323};
324
325/**
326 * Return an ETag in the form of `"<size>-<mtime>"`
327 * from the given `stat`.
328 *
329 * @param {Object} stat
330 * @return {String}
331 * @api private
332 */
333
3341exports.etag = function(stat) {
3350 return '"' + stat.size + '-' + Number(stat.mtime) + '"';
336};
337
338/**
339 * Parse the given Cache-Control `str`.
340 *
341 * @param {String} str
342 * @return {Object}
343 * @api private
344 */
345
3461exports.parseCacheControl = function(str){
3470 var directives = str.split(',')
348 , obj = {};
349
3500 for(var i = 0, len = directives.length; i < len; i++) {
3510 var parts = directives[i].split('=')
352 , key = parts.shift().trim()
353 , val = parseInt(parts.shift(), 10);
354
3550 obj[key] = isNaN(val) ? true : val;
356 }
357
3580 return obj;
359};
360
361/**
362 * Parse the `req` url with memoization.
363 *
364 * @param {ServerRequest} req
365 * @return {Object}
366 * @api private
367 */
368
3691exports.parseUrl = function(req){
3700 var parsed = req._parsedUrl;
3710 if (parsed && parsed.href == req.url) {
3720 return parsed;
373 } else {
3740 parsed = parse(req.url);
375
3760 if (parsed.auth && !parsed.protocol && ~parsed.href.indexOf('//')) {
377 // This parses pathnames, and a strange pathname like //r@e should work
3780 parsed = parse(req.url.replace(/@/g, '%40'));
379 }
380
3810 return req._parsedUrl = parsed;
382 }
383};
384
385/**
386 * Parse byte `size` string.
387 *
388 * @param {String} size
389 * @return {Number}
390 * @api private
391 */
392
3931exports.parseBytes = require('bytes');
394
395/**
396 * Normalizes the path separator from system separator
397 * to URL separator, aka `/`.
398 *
399 * @param {String} path
400 * @return {String}
401 * @api private
402 */
403
4041exports.normalizeSlashes = function normalizeSlashes(path) {
4050 return path.split(sep).join('/');
406};
407
4081function noop() {}
409

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/node_modules/debug/lib/debug.js

47%
46
22
24
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var tty = require('tty');
6
7/**
8 * Expose `debug()` as the module.
9 */
10
111module.exports = debug;
12
13/**
14 * Enabled debuggers.
15 */
16
171var names = []
18 , skips = [];
19
201(process.env.DEBUG || '')
21 .split(/[\s,]+/)
22 .forEach(function(name){
231 name = name.replace('*', '.*?');
241 if (name[0] === '-') {
250 skips.push(new RegExp('^' + name.substr(1) + '$'));
26 } else {
271 names.push(new RegExp('^' + name + '$'));
28 }
29 });
30
31/**
32 * Colors.
33 */
34
351var colors = [6, 2, 3, 4, 5, 1];
36
37/**
38 * Previous debug() call.
39 */
40
411var prev = {};
42
43/**
44 * Previously assigned color.
45 */
46
471var prevColor = 0;
48
49/**
50 * Is stdout a TTY? Colored output is disabled when `true`.
51 */
52
531var isatty = tty.isatty(2);
54
55/**
56 * Select a color.
57 *
58 * @return {Number}
59 * @api private
60 */
61
621function color() {
630 return colors[prevColor++ % colors.length];
64}
65
66/**
67 * Humanize the given `ms`.
68 *
69 * @param {Number} m
70 * @return {String}
71 * @api private
72 */
73
741function humanize(ms) {
750 var sec = 1000
76 , min = 60 * 1000
77 , hour = 60 * min;
78
790 if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
800 if (ms >= min) return (ms / min).toFixed(1) + 'm';
810 if (ms >= sec) return (ms / sec | 0) + 's';
820 return ms + 'ms';
83}
84
85/**
86 * Create a debugger with the given `name`.
87 *
88 * @param {String} name
89 * @return {Type}
90 * @api public
91 */
92
931function debug(name) {
944 function disabled(){}
954 disabled.enabled = false;
96
974 var match = skips.some(function(re){
980 return re.test(name);
99 });
100
1014 if (match) return disabled;
102
1034 match = names.some(function(re){
1044 return re.test(name);
105 });
106
1078 if (!match) return disabled;
1080 var c = color();
109
1100 function colored(fmt) {
1110 fmt = coerce(fmt);
112
1130 var curr = new Date;
1140 var ms = curr - (prev[name] || curr);
1150 prev[name] = curr;
116
1170 fmt = ' \u001b[9' + c + 'm' + name + ' '
118 + '\u001b[3' + c + 'm\u001b[90m'
119 + fmt + '\u001b[3' + c + 'm'
120 + ' +' + humanize(ms) + '\u001b[0m';
121
1220 console.error.apply(this, arguments);
123 }
124
1250 function plain(fmt) {
1260 fmt = coerce(fmt);
127
1280 fmt = new Date().toUTCString()
129 + ' ' + name + ' ' + fmt;
1300 console.error.apply(this, arguments);
131 }
132
1330 colored.enabled = plain.enabled = true;
134
1350 return isatty || process.env.DEBUG_COLORS
136 ? colored
137 : plain;
138}
139
140/**
141 * Coerce `val`.
142 */
143
1441function coerce(val) {
1450 if (val instanceof Error) return val.stack || val.message;
1460 return val;
147}
148

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/node_modules/send/lib/send.js

17%
151
26
125
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var debug = require('debug')('send')
7 , parseRange = require('range-parser')
8 , Stream = require('stream')
9 , mime = require('mime')
10 , fresh = require('fresh')
11 , path = require('path')
12 , http = require('http')
13 , fs = require('fs')
14 , basename = path.basename
15 , normalize = path.normalize
16 , join = path.join
17 , utils = require('./utils');
18
19/**
20 * Expose `send`.
21 */
22
231exports = module.exports = send;
24
25/**
26 * Expose mime module.
27 */
28
291exports.mime = mime;
30
31/**
32 * Return a `SendStream` for `req` and `path`.
33 *
34 * @param {Request} req
35 * @param {String} path
36 * @param {Object} options
37 * @return {SendStream}
38 * @api public
39 */
40
411function send(req, path, options) {
420 return new SendStream(req, path, options);
43}
44
45/**
46 * Initialize a `SendStream` with the given `path`.
47 *
48 * Events:
49 *
50 * - `error` an error occurred
51 * - `stream` file streaming has started
52 * - `end` streaming has completed
53 * - `directory` a directory was requested
54 *
55 * @param {Request} req
56 * @param {String} path
57 * @param {Object} options
58 * @api private
59 */
60
611function SendStream(req, path, options) {
620 var self = this;
630 this.req = req;
640 this.path = path;
650 this.options = options || {};
660 this.maxage(0);
670 this.hidden(false);
680 this.index('index.html');
69}
70
71/**
72 * Inherits from `Stream.prototype`.
73 */
74
751SendStream.prototype.__proto__ = Stream.prototype;
76
77/**
78 * Enable or disable "hidden" (dot) files.
79 *
80 * @param {Boolean} path
81 * @return {SendStream}
82 * @api public
83 */
84
851SendStream.prototype.hidden = function(val){
860 debug('hidden %s', val);
870 this._hidden = val;
880 return this;
89};
90
91/**
92 * Set index `path`, set to a falsy
93 * value to disable index support.
94 *
95 * @param {String|Boolean} path
96 * @return {SendStream}
97 * @api public
98 */
99
1001SendStream.prototype.index = function(path){
1010 debug('index %s', path);
1020 this._index = path;
1030 return this;
104};
105
106/**
107 * Set root `path`.
108 *
109 * @param {String} path
110 * @return {SendStream}
111 * @api public
112 */
113
1141SendStream.prototype.root =
115SendStream.prototype.from = function(path){
1160 this._root = normalize(path);
1170 return this;
118};
119
120/**
121 * Set max-age to `ms`.
122 *
123 * @param {Number} ms
124 * @return {SendStream}
125 * @api public
126 */
127
1281SendStream.prototype.maxage = function(ms){
1290 if (Infinity == ms) ms = 60 * 60 * 24 * 365 * 1000;
1300 debug('max-age %d', ms);
1310 this._maxage = ms;
1320 return this;
133};
134
135/**
136 * Emit error with `status`.
137 *
138 * @param {Number} status
139 * @api private
140 */
141
1421SendStream.prototype.error = function(status, err){
1430 var res = this.res;
1440 var msg = http.STATUS_CODES[status];
1450 err = err || new Error(msg);
1460 err.status = status;
1470 if (this.listeners('error').length) return this.emit('error', err);
1480 res.statusCode = err.status;
1490 res.end(msg);
150};
151
152/**
153 * Check if the pathname is potentially malicious.
154 *
155 * @return {Boolean}
156 * @api private
157 */
158
1591SendStream.prototype.isMalicious = function(){
1600 return !this._root && ~this.path.indexOf('..');
161};
162
163/**
164 * Check if the pathname ends with "/".
165 *
166 * @return {Boolean}
167 * @api private
168 */
169
1701SendStream.prototype.hasTrailingSlash = function(){
1710 return '/' == this.path[this.path.length - 1];
172};
173
174/**
175 * Check if the basename leads with ".".
176 *
177 * @return {Boolean}
178 * @api private
179 */
180
1811SendStream.prototype.hasLeadingDot = function(){
1820 return '.' == basename(this.path)[0];
183};
184
185/**
186 * Check if this is a conditional GET request.
187 *
188 * @return {Boolean}
189 * @api private
190 */
191
1921SendStream.prototype.isConditionalGET = function(){
1930 return this.req.headers['if-none-match']
194 || this.req.headers['if-modified-since'];
195};
196
197/**
198 * Strip content-* header fields.
199 *
200 * @api private
201 */
202
2031SendStream.prototype.removeContentHeaderFields = function(){
2040 var res = this.res;
2050 Object.keys(res._headers).forEach(function(field){
2060 if (0 == field.indexOf('content')) {
2070 res.removeHeader(field);
208 }
209 });
210};
211
212/**
213 * Respond with 304 not modified.
214 *
215 * @api private
216 */
217
2181SendStream.prototype.notModified = function(){
2190 var res = this.res;
2200 debug('not modified');
2210 this.removeContentHeaderFields();
2220 res.statusCode = 304;
2230 res.end();
224};
225
226/**
227 * Check if the request is cacheable, aka
228 * responded with 2xx or 304 (see RFC 2616 section 14.2{5,6}).
229 *
230 * @return {Boolean}
231 * @api private
232 */
233
2341SendStream.prototype.isCachable = function(){
2350 var res = this.res;
2360 return (res.statusCode >= 200 && res.statusCode < 300) || 304 == res.statusCode;
237};
238
239/**
240 * Handle stat() error.
241 *
242 * @param {Error} err
243 * @api private
244 */
245
2461SendStream.prototype.onStatError = function(err){
2470 var notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'];
2480 if (~notfound.indexOf(err.code)) return this.error(404, err);
2490 this.error(500, err);
250};
251
252/**
253 * Check if the cache is fresh.
254 *
255 * @return {Boolean}
256 * @api private
257 */
258
2591SendStream.prototype.isFresh = function(){
2600 return fresh(this.req.headers, this.res._headers);
261};
262
263/**
264 * Redirect to `path`.
265 *
266 * @param {String} path
267 * @api private
268 */
269
2701SendStream.prototype.redirect = function(path){
2710 if (this.listeners('directory').length) return this.emit('directory');
2720 var res = this.res;
2730 path += '/';
2740 res.statusCode = 301;
2750 res.setHeader('Location', path);
2760 res.end('Redirecting to ' + utils.escape(path));
277};
278
279/**
280 * Pipe to `res.
281 *
282 * @param {Stream} res
283 * @return {Stream} res
284 * @api public
285 */
286
2871SendStream.prototype.pipe = function(res){
2880 var self = this
289 , args = arguments
290 , path = this.path
291 , root = this._root;
292
293 // references
2940 this.res = res;
295
296 // invalid request uri
2970 path = utils.decode(path);
2980 if (-1 == path) return this.error(400);
299
300 // null byte(s)
3010 if (~path.indexOf('\0')) return this.error(400);
302
303 // join / normalize from optional root dir
3040 if (root) path = normalize(join(this._root, path));
305
306 // ".." is malicious without "root"
3070 if (this.isMalicious()) return this.error(403);
308
309 // malicious path
3100 if (root && 0 != path.indexOf(root)) return this.error(403);
311
312 // hidden file support
3130 if (!this._hidden && this.hasLeadingDot()) return this.error(404);
314
315 // index file support
3160 if (this._index && this.hasTrailingSlash()) path += this._index;
317
3180 debug('stat "%s"', path);
3190 fs.stat(path, function(err, stat){
3200 if (err) return self.onStatError(err);
3210 if (stat.isDirectory()) return self.redirect(self.path);
3220 self.emit('file', path, stat);
3230 self.send(path, stat);
324 });
325
3260 return res;
327};
328
329/**
330 * Transfer `path`.
331 *
332 * @param {String} path
333 * @api public
334 */
335
3361SendStream.prototype.send = function(path, stat){
3370 var options = this.options;
3380 var len = stat.size;
3390 var res = this.res;
3400 var req = this.req;
3410 var ranges = req.headers.range;
3420 var offset = options.start || 0;
343
344 // set header fields
3450 this.setHeader(stat);
346
347 // set content-type
3480 this.type(path);
349
350 // conditional GET support
3510 if (this.isConditionalGET()
352 && this.isCachable()
353 && this.isFresh()) {
3540 return this.notModified();
355 }
356
357 // adjust len to start/end options
3580 len = Math.max(0, len - offset);
3590 if (options.end !== undefined) {
3600 var bytes = options.end - offset + 1;
3610 if (len > bytes) len = bytes;
362 }
363
364 // Range support
3650 if (ranges) {
3660 ranges = parseRange(len, ranges);
367
368 // unsatisfiable
3690 if (-1 == ranges) {
3700 res.setHeader('Content-Range', 'bytes */' + stat.size);
3710 return this.error(416);
372 }
373
374 // valid (syntactically invalid ranges are treated as a regular response)
3750 if (-2 != ranges) {
3760 options.start = offset + ranges[0].start;
3770 options.end = offset + ranges[0].end;
378
379 // Content-Range
3800 res.statusCode = 206;
3810 res.setHeader('Content-Range', 'bytes '
382 + ranges[0].start
383 + '-'
384 + ranges[0].end
385 + '/'
386 + len);
3870 len = options.end - options.start + 1;
388 }
389 }
390
391 // content-length
3920 res.setHeader('Content-Length', len);
393
394 // HEAD support
3950 if ('HEAD' == req.method) return res.end();
396
3970 this.stream(path, options);
398};
399
400/**
401 * Stream `path` to the response.
402 *
403 * @param {String} path
404 * @param {Object} options
405 * @api private
406 */
407
4081SendStream.prototype.stream = function(path, options){
409 // TODO: this is all lame, refactor meeee
4100 var self = this;
4110 var res = this.res;
4120 var req = this.req;
413
414 // pipe
4150 var stream = fs.createReadStream(path, options);
4160 this.emit('stream', stream);
4170 stream.pipe(res);
418
419 // socket closed, done with the fd
4200 req.on('close', stream.destroy.bind(stream));
421
422 // error handling code-smell
4230 stream.on('error', function(err){
424 // no hope in responding
4250 if (res._header) {
4260 console.error(err.stack);
4270 req.destroy();
4280 return;
429 }
430
431 // 500
4320 err.status = 500;
4330 self.emit('error', err);
434 });
435
436 // end
4370 stream.on('end', function(){
4380 self.emit('end');
439 });
440};
441
442/**
443 * Set content-type based on `path`
444 * if it hasn't been explicitly set.
445 *
446 * @param {String} path
447 * @api private
448 */
449
4501SendStream.prototype.type = function(path){
4510 var res = this.res;
4520 if (res.getHeader('Content-Type')) return;
4530 var type = mime.lookup(path);
4540 var charset = mime.charsets.lookup(type);
4550 debug('content-type %s', type);
4560 res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
457};
458
459/**
460 * Set reaponse header fields, most
461 * fields may be pre-defined.
462 *
463 * @param {Object} stat
464 * @api private
465 */
466
4671SendStream.prototype.setHeader = function(stat){
4680 var res = this.res;
4690 if (!res.getHeader('Accept-Ranges')) res.setHeader('Accept-Ranges', 'bytes');
4700 if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat));
4710 if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString());
4720 if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (this._maxage / 1000));
4730 if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString());
474};
475

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/express/node_modules/send/lib/utils.js

37%
8
3
5
LineHitsSource
1
2/**
3 * Return an ETag in the form of `"<size>-<mtime>"`
4 * from the given `stat`.
5 *
6 * @param {Object} stat
7 * @return {String}
8 * @api private
9 */
10
111exports.etag = function(stat) {
120 return '"' + stat.size + '-' + Number(stat.mtime) + '"';
13};
14
15/**
16 * decodeURIComponent.
17 *
18 * Allows V8 to only deoptimize this fn instead of all
19 * of send().
20 *
21 * @param {String} path
22 * @api private
23 */
24
251exports.decode = function(path){
260 try {
270 return decodeURIComponent(path);
28 } catch (err) {
290 return -1;
30 }
31};
32
33/**
34 * Escape the given string of `html`.
35 *
36 * @param {String} html
37 * @return {String}
38 * @api private
39 */
40
411exports.escape = function(html){
420 return String(html)
43 .replace(/&(?!\w+;)/g, '&')
44 .replace(/</g, '<')
45 .replace(/>/g, '>')
46 .replace(/"/g, '"');
47};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/appcore.js

5%
115
6
109
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
18/*jshint maxstatements:35, maxcomplexity:10*/
191'use strict';
20
211var Q = require('q'),
22 tls = require('tls'),
23 express = require('express'),
24 enrouten = require('express-enrouten'),
25 patch = require('./patch'),
26 kraken = require('./middleware'),
27 util = require('./util'),
28 pathutil = util.pathutil,
29 config = util.configutil;
30
31
321var proto = {
33
34 init: function (callback) {
350 this._configure(callback);
36 },
37
38
39 _configure: function (callback) {
400 var self, app;
41
420 self = this;
430 app = this._app;
44
450 function next(err) {
460 var config, settings;
47
480 if (err) {
490 callback(err);
500 return;
51 }
52
530 config = self._config;
540 patch.apply('config', app, config);
55
56 // XXX: Special-case resolving `express:views` until we get config protocols working.
570 config.set('express:views', self._resolve(config.get('express:views')));
580 config.set('express:env', config.get('env:env'));
590 config.set('express:port', config.port);
600 config.set('express:host', config.host);
61
620 settings = config.get('express');
630 Object.keys(settings).forEach(function (key) {
640 app.set(key, settings[key]);
65 });
66
670 settings = config.get('ssl');
68
690 if (settings) {
700 app.set('ssl', settings);
710 tls.SLAB_BUFFER_SIZE = settings.slabBufferSize || tls.SLAB_BUFFER_SIZE;
720 tls.CLIENT_RENEG_LIMIT = settings.clientRenegotiationLimit || tls.CLIENT_RENEG_LIMIT;
730 tls.CLIENT_RENEG_WINDOW = settings.clientRenegotiationWindow || tls.CLIENT_RENEG_WINDOW;
74 }
75
760 app.get('view engine') && self._views();
770 self._middleware();
780 callback();
79 }
80
81
820 this._config = config.create(this._resolve('.'));
83
840 if (typeof this._delegate.configure === 'function') {
850 this._delegate.configure(this._config.raw, next);
860 return;
87 }
88
890 next();
90 },
91
92
93 _views: function () {
940 var app, config, i18n, cache, engines, module;
95
96 /**
97 * XXXXX ACHTUNG! ALERT! ALERT! PELIGRO! XXXXX
98 * The following code is brittle and needs refactoring. It has already been the
99 * source of many bugs and smells terrible. Consider getting kraken out of the
100 * i18n game altogether.
101 */
102
1030 app = this._app;
1040 config = this._config;
105
106 // If i18n is enabled (config is available), set its cache
107 // to the view cache value, and disable the view cache.
1080 i18n = config.get('i18n');
1090 cache = config.get('express:view cache');
1100 if (i18n) {
111 // Set i18n to the view engine cache settings. If the view
112 // engine cache is enabled, disable it so i18n can take over.
113 // Either way caching is still enabled, so renderer caches will
114 // still be disabled below.
1150 i18n.cache = cache;
1160 if (cache) {
1170 app.set('view cache', false);
1180 config.set('express:view cache', false);
119 }
120 }
121
122
123 // Register each rendering engine
1240 engines = config.get('view engines');
1250 Object.keys(engines).forEach(function (ext) {
1260 var meta, engine, renderer;
127
1280 meta = engines[ext];
1290 engine = require(meta.module);
1300 renderer = engine[ext];
131
132 // Assume a single argument renderer means it's actually a factory
133 // method and needs to be configured.
1340 if (typeof renderer === 'function' && renderer.length === 1) {
135 // Now create the real renderer. If express cache is enabled
136 // favor that over view engine cache.
1370 meta.settings = meta.settings || {};
1380 meta.settings.cache = (cache === true) ? false : meta.settings.cache;
1390 renderer = renderer(meta.settings);
140 }
141
1420 app.engine(ext, renderer);
143 });
144
1450 if (i18n) {
146 // After all engines are registered, apply i18n. It needs to know
147 // about the state of the current view engine in order to work. :/
1480 module = util.tryRequire('makara');
1490 i18n.contentPath = this._resolve(i18n.contentPath);
1500 this._i18n = module && module.create(app, i18n);
151 }
152
153 },
154
155
156 _middleware: function () {
1570 var app, delegate, config, srcRoot, staticRoot, errorPages;
158
1590 app = this._app;
1600 delegate = this._delegate;
1610 config = this._config.get('middleware');
1620 srcRoot = this._resolve(config.static.srcRoot);
1630 staticRoot = this._resolve(config.static.rootPath);
1640 errorPages = config.errorPages || {};
165
1660 app.use(kraken.shutdown(app, this._config, errorPages['503']));
1670 app.use(express.favicon());
1680 app.use(kraken.compiler(srcRoot, staticRoot, this._config, this._i18n));
1690 app.use(express.static(staticRoot));
1700 app.use(kraken.logger(config.logger));
171
1720 if (typeof delegate.requestStart === 'function') {
1730 delegate.requestStart(app);
174 }
175
1760 app.use(express.json(config.json));
1770 app.use(express.urlencoded(config.urlencoded));
178
1790 if (config.multipart) {
1800 app.use(kraken.multipart(config.multipart.params));
181 }
182
1830 app.use(express.cookieParser(config.session.secret));
1840 app.use(kraken.session(config.session));
1850 app.use(kraken.appsec(config.appsec));
186
1870 if (typeof delegate.requestBeforeRoute === 'function') {
1880 delegate.requestBeforeRoute(app);
189 }
190
1910 enrouten(app).withRoutes({
192 directory: this._resolve(this._config.get('routes:routePath'))
193 });
194
1950 if (typeof delegate.requestAfterRoute === 'function') {
1960 delegate.requestAfterRoute(app);
197 }
198
1990 app.use(kraken.fileNotFound(errorPages['404']));
2000 app.use(kraken.serverError(errorPages['500']));
2010 app.use(kraken.errorHandler(config.errorHandler));
202 },
203
204 _resolve: function (path) {
2050 return this._resolver.resolve(path);
206 }
207};
208
209
2101function create(delegate, resolver, callback) {
2110 var app, appcore;
212
2130 if (isExpress(delegate)) {
2140 callback(null, delegate);
2150 return;
216 }
217
2180 if (typeof resolver === 'function') {
2190 callback = resolver;
2200 resolver = pathutil.create();
221 }
222
2230 app = express();
2240 if (!delegate) {
2250 patch.apply('stream', app);
2260 callback(null, app);
2270 return;
228 }
229
2300 appcore = Object.create(proto, {
231 _app: {
232 enumerable: true,
233 writable: false,
234 value: app
235 },
236 _delegate: {
237 enumerable: true,
238 writable: false,
239 value: delegate
240 },
241 _resolver: {
242 enumerable: true,
243 writable: false,
244 value: resolver
245 },
246 _config: {
247 enumerable: true,
248 writable: true,
249 value: undefined
250 },
251 _i18n: {
252 enumerable: true,
253 writable: true,
254 value: undefined
255 }
256 });
257
2580 appcore.init(function (err) {
2590 if (err) {
2600 callback(err);
2610 return;
262 }
2630 callback(null, app);
264 });
265}
266
267
2681function isExpress(obj) {
2690 return typeof obj === 'function' && obj.handle && obj.set;
270}
271
272
2731exports.create = function (delegate, resolver, callback) {
2740 if (!callback) {
2750 return Q.nfbind(create)(delegate, resolver);
276 }
277
2780 setImmediate(create.bind(null, delegate, resolver, callback));
279};
280

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/middleware/compiler.js

9%
32
3
29
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
201var fs = require('fs'),
21 path = require('path'),
22 rimraf = require('rimraf'),
23 mkdirp = require('mkdirp'),
24 devtools = require('kraken-devtools'),
25 util = require('../util');
26
27
281module.exports = function (srcRoot, destRoot, config, intl) {
290 var i18n, dust, options, directory;
30
310 i18n = config.get('i18n');
320 dust = util.tryRequire('dustjs-linkedin');
330 options = config.get('middleware:compiler');
340 directory = options && options.dust;
35
36
370 if (i18n && util.tryRequire('makara') && dust && directory) {
38
390 options.dust = {
40
41 dir: directory,
42
43 precompile: function (context, callback) {
440 var locality, locale, dest;
45
46 // Look for Country/Locale tuple in path
470 locale = context.name.match(/(?:([A-Za-z]{2})\/([A-Za-z]{2})\/)?(.*)/);
480 if (locale && locale[1] && locale[2]) {
490 locality = {
50 country: locale[1],
51 language: locale[2]
52 };
53 }
54
550 if (locale[3]) {
560 context.name = locale[3];
57 }
58
59 // Store original source root and switch it so a tmp directory.
600 context.origSrcRoot = context.srcRoot;
610 context.srcRoot = path.join(context.srcRoot, 'tmp');
62
63 // Determine the interim tempfile (a preprocessed dust file)
640 dest = path.join(context.srcRoot, context.filePath);
650 dest = dest.replace(path.extname(dest), '') + '.dust';
66
670 intl.localize(context.name, locality, function (err, data) {
680 if (err) {
690 callback(err);
700 return;
71 }
72
730 mkdirp(path.dirname(dest), function (err) {
740 if (err) {
750 callback(err);
760 return;
77 }
780 fs.writeFile(dest, data, function (err) {
790 callback(err, context);
80 });
81 });
82
83 });
84
85 },
86
87 postcompile: function (context, callback) {
88 // Remove temp files
890 rimraf(context.srcRoot, callback);
90 }
91
92 };
93 }
94
950 return devtools.compiler(srcRoot, destRoot, options);
96};
97

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/middleware/error.js

20%
24
5
19
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
201var express = require('express'),
21 util = require('../util');
22
23
241exports.defaultHandler = function (settings) {
250 var handler = util.tryRequire(settings && settings.module, express.errorHandler);
260 return handler(settings);
27};
28
291exports.fileNotFound = function (template) {
300 return function (req, res, next) {
310 var model = { url: req.url };
32
330 if (template) {
340 if (req.xhr) {
350 res.send(404, model);
36 } else {
370 res.status(404);
380 res.render(template, model);
39 }
40 } else {
410 next();
42 }
43 };
44};
45
46
471exports.serverError = function (template) {
480 return function (err, req, res, next) {
490 var model = { url: req.url, err: err };
50
510 console.error('Error:' + err.message);
52
530 if (template) {
540 if (req.xhr) {
550 res.send(500, model);
56 } else {
570 res.status(500);
580 res.render(template, model);
59 }
60 } else {
610 next(err);
62 }
63 };
64};
65

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/middleware/index.js

100%
3
3
0
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
201var error = require('./error');
21
22
231exports = module.exports = {
24
25 logger: require('./logger'),
26
27 session: require('./session'),
28
29 appsec: require('lusca'),
30
31 multipart: require('./multipart'),
32
33 shutdown: require('./shutdown'),
34
35 compiler: require('./compiler'),
36
37 fileNotFound: error.fileNotFound,
38
39 serverError: error.serverError,
40
41 errorHandler: error.defaultHandler
42
43};
44

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/middleware/logger.js

42%
7
3
4
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
201var express = require('express'),
21 util = require('../util');
22
23
24// NOTE: It's possible for clients to define middleware by name or fall back to a default as defined
25// by kraken. This takes advantage of node module lookup rules, thus will use the module
26// available in the parent module as it won't be available in the current module.
271module.exports = function (settings) {
280 var override = util.tryRequire(settings && settings.module, express.logger);
290 if (typeof override === 'object' && typeof override.logger === 'function') {
300 override = override.logger;
31 }
320 return override(settings);
33};
34

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/middleware/multipart.js

11%
27
3
24
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
201var formidable = require('formidable'),
21 fs = require('fs');
22
231module.exports = function (settings) {
240 settings = typeof settings === 'object' ? settings : {};
25
260 return function (req, res, next) {
270 var form = new formidable.IncomingForm(settings), contentType = req.headers['content-type'];
28
290 if (typeof contentType === 'string' && contentType.indexOf('multipart/form-data') > -1) {
300 form.parse(req, function (err, fields, files) {
310 if (err) {
320 next(err);
330 return;
34 }
350 req.body = fields; // pass along form fields
360 req.files = files; // pass along files
37
38 // remove tmp files after request finishes
390 var cleanup = function () {
40
41 // remove tmp file(s)
420 Object.keys(files).forEach(function (file) {
430 var filePath = files[file].path;
440 if (typeof filePath === 'string') {
450 fs.exists(filePath, function (exists) {
460 if (exists) {
470 fs.unlink(filePath, function (err) {
480 if (err) {
490 console.error('Kraken failed to remove tmp file: ' + filePath);
500 console.error(err);
51 }
52 });
53 }
54 });
55 }
56 });
57 };
580 res.once('finish', cleanup);
590 res.once('close', cleanup);
600 next();
61 });
62 }
63 else {
640 next();
65 }
66 };
67
68};
69

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/middleware/session.js

33%
9
3
6
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
201var express = require('express'),
21 util = require('../util');
22
23
241module.exports = function (settings) {
250 var override, Store;
26
270 override = util.tryRequire(settings && settings.module);
280 if (override) {
290 Store = override(express);
300 settings.store = new Store(settings.config);
31 }
32
330 return express.session(settings);
34};
35

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/middleware/shutdown.js

9%
21
2
19
LineHitsSource
1/***@@@ BEGIN LICENSE @@@***/
2/*───────────────────────────────────────────────────────────────────────────*\
3│ Copyright (C) 2014 eBay Software Foundation │
4│ │
5│hh ,'""`. │
6│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
7│ |(@)(@)| you may not use this file except in compliance with the License. │
8│ ) __ ( You may obtain a copy of the License at │
9│ /,'))((`.\ │
10│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
11│ `\ `)(' /' │
12│ │
13│ Unless required by applicable law or agreed to in writing, software │
14│ distributed under the License is distributed on an "AS IS" BASIS, │
15│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
16│ See the License for the specific language governing permissions and │
17│ limitations under the License. │
18\*───────────────────────────────────────────────────────────────────────────*/
19/***@@@ END LICENSE @@@***/
201'use strict';
21
221module.exports = function (app, config, template) {
23
240 var gracefulShutdown = function () {
250 var server, timeout;
260 config.set('kraken:state', 'disconnecting');
27
280 server = app.get('kraken:server');
29 // switch to kraken.close once it's implemented
300 server.close(function () {
310 process.exit();
32 });
33
340 timeout = config.get('shutdownTimeout');
350 setTimeout(function () {
360 process.exit(1);
37 }, timeout);
38 };
39
400 process.on('SIGTERM', gracefulShutdown);
410 process.on('SIGINT', gracefulShutdown);
42
430 return function (req, res, next) {
440 if (config.get('kraken:state') !== 'disconnecting') {
450 return next();
46 }
470 res.setHeader('Connection', 'close');
480 if (template && !req.xhr) {
490 res.status(503);
500 res.render(template);
51 } else {
520 res.send(503, 'Server is in the process of shutting down.');
53 }
54 };
55
56};
57

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/patch/config.js

11%
27
3
24
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
201var assert = require('assert');
21
22/**
23 * Contains all the logic to map old config settings to new
24 * settings. When we no longer want to support old config,
25 * this can go away.
26 * @param app
27 * @param config
28 */
291exports.apply = function (app, config) {
300 var views, engine, module, engines, existing, proxy;
31
32 // Map old viewEngine config to new
330 views = config.get('viewEngine');
340 if (views) {
35
360 console.warn('`viewEngine` configuration is deprecated. Please see documentation for details.');
37
380 if (views.cache !== undefined) {
390 config.set('express:view cache', views.cache);
400 delete views.cache;
41 }
42
430 if (views.templatePath !== undefined) {
440 config.set('express:views', views.templatePath);
450 delete views.templatePath;
46 }
47
48 // There should ALWAYS be an engine, either in old or new config.
490 engine = views.ext || config.get('express:view engine');
500 assert(engine, 'No view engine configured.');
510 config.set('express:view engine', engine);
520 delete views.ext;
53
540 module = views.module;
550 delete views.module;
56
57 // Ok, if an engine is defined first check the new config style to
58 // see if we need to overwrite/merge `module` and `settings` or create
59 // a new entry altogether.
600 existing = config.get('view engines:' + engine) || {
61 module: undefined,
62 settings: {}
63 };
64
65 // No module was defined, so don't overwrite. Then update the engine config,
66 // and finally set the settings directly so the values of `views` get merged
67 // into the object instead of overwritten.
680 module && (existing.module = module);
690 config.set('view engines:' + engine, existing);
700 config.set('view engines:' + engine + ':settings', views);
710 config.remove('viewEngine');
72 }
73
74 // Map old proxy config to new
750 proxy = config.get('proxy:trust');
760 if (proxy !== undefined) {
770 config.set('express:trust proxy', config.get('proxy:trust'));
78 }
79};
80

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/patch/index.js

30%
10
3
7
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
201var patches = {
21 stream: require('./stream'),
22 config: require('./config')
23};
24
25/**
26 * This feature add the ability to apply names patches to express. Usually,
27 * this practice is risky as it has dependencies on express internals, thus
28 * is separate from core application code.
29 */
301exports.apply = function (names, app, config) {
31
320 names = names.split(/\s*,\s*/);
330 names.forEach(function (name) {
340 var patch;
35
360 if (!(name in patches)) {
370 throw new Error('Patch ' + name + ' not found.');
38 }
39
400 patch = patches[name];
410 patch.apply(app, config);
42 });
43
44};
45

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/patch/stream.js

13%
22
3
19
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
18/*jshint proto:true*/
191'use strict';
20
211var Stream = require('stream');
22
23/**
24 * This express patch allows rendering engines to return a stream
25 * instead of a string to pipe responses to the client on render.
26 * @param app and express application.
27 */
281exports.apply = function (app) {
29
300 app.response = {
31
32 __proto__: app.response,
33
34 super_: app.response,
35
36 render: function (view, options, fn) {
370 var self = this;
38
390 if (typeof options === 'function') {
400 fn = options;
410 options = {};
42 }
43
440 fn = fn || function (err, str) {
450 if (err) {
460 self.req.next(err);
470 return;
48 }
49
500 if (str instanceof Stream) {
51 // If content length was somehow added, remove it. Not applicable.
520 self.removeHeader('Content-Length');
53
54 // Set appropriate headers for this payload.
55 // TODO: ETags? Don't really see how, but who knows.
560 self.set('Transfer-Encoding', 'chunked');
570 if (!self.get('Content-Type')) {
580 self.charset = self.charset || 'utf-8';
590 self.type('html');
60 }
61
620 str.pipe(self);
630 return;
64 }
65
660 self.send(str);
67 };
68
690 this.super_.render.call(this, view, options, fn);
70 }
71 };
72
73};
74

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/util/configutil.js

11%
96
11
85
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
201var fs = require('fs'),
21 path = require('path'),
22 nconf = require('nconf'),
23 shortstop = require('shortstop');
24
25// Patches JSON
261require('jsonminify');
27
28
29
301function Configurator(appRoot) {
31 // Setup default memory store with settings from command line and env.
320 this._nconf = nconf;
330 this._resolver = shortstop.create();
340 this._init(appRoot);
35}
36
37
381Configurator.Protocol = {
39 path: function (value) {
400 if (path.resolve(value) === value) {
41 // Absolute path already, so just return it.
420 return value;
43 }
440 value = value.split('/');
450 value.unshift(nconf.get('appRoot'));
460 return path.resolve.apply(path, value);
47 },
48 file: function (value) {
490 value = Configurator.Protocol.path(value);
500 return fs.readFileSync(value);
51 },
52 base64: function (value) {
530 return new Buffer(value, 'base64');
54 }
55
56};
57
58
591Configurator.ENVIRONMENTS = {
60 development: /^dev/i,
61 test : /^test/i,
62 staging : /^stag/i,
63 production : /^prod/i
64};
65
66
67/**
68 * Helper function to find out if the provided dir is the filesystem root.
69 * @param dir the directory in question
70 * @returns {boolean} true if we're at the filesystem root, false if not.
71 */
721Configurator.isSystemRoot = function (dir) {
730 return path.dirname(dir) === dir;
74};
75
76
771Configurator.prototype = {
78
79 /**
80 * Read the provided files and put their contents into nconf, resolving possible
81 * env-specific files/config.
82 * @param root
83 * @param files
84 */
85 load: function load(root, files) {
860 var file, store, env, ext;
87
880 env = nconf.get('env:env');
890 ext = '.json';
90
910 root = this._findConfigRoot(root);
920 if (!root) {
930 return this;
94 }
95
96 // Include env-specific files...
970 files.forEach(function (fileName) {
980 file = path.join(root, fileName + '-' + env + ext);
990 store = this._createJsonStore(file);
100
1010 if (store) {
1020 nconf.use(file, store);
103 }
104 }, this);
105
106 // Then, include base files...
1070 files.forEach(function (fileName) {
1080 file = path.join(root, fileName + ext);
1090 store = this._createJsonStore(file);
110
1110 if (store) {
1120 nconf.use(file, store);
113 }
114 }, this);
115
1160 return this;
117 },
118
119
120 done: function () {
1210 return this._nconf;
122 },
123
124
125 /**
126 * Adds convenience properties for determining the application's
127 * current environment (dev, test, prod, etc), configures protocol, etc.
128 */
129 _init: function init(appRoot) {
1300 var nconf, env;
131
132 // Configure environment convenience properties.
1330 nconf = this._nconf;
134
1350 nconf.argv().env().use('memory');
1360 env = nconf.get('NODE_ENV') || 'development';
1370 nconf.set('NODE_ENV', env);
1380 nconf.set('env:env', env);
1390 nconf.set('env:' + env, true);
1400 nconf.set('appRoot', appRoot);
141
1420 Object.keys(Configurator.ENVIRONMENTS).forEach(function (key) {
1430 nconf.set('env:' + key, !!env.match(Configurator.ENVIRONMENTS[key]));
144 });
145
146 // Configure protocol handlers
1470 Object.keys(Configurator.Protocol).forEach(function (protocol) {
1480 this._resolver.use(protocol, Configurator.Protocol[protocol]);
149 }, this);
150 },
151
152
153 /**
154 * Find the first config directory starting at the provided root.
155 * @param dir the directory from which to start searching for the config dir.
156 * @returns {undefined} the config directory or undefined if not found.
157 */
158 _findConfigRoot: function (dir) {
1590 var pkg, root, exists;
160
1610 do {
162
1630 pkg = path.join(dir, 'config');
1640 dir = path.dirname(dir);
1650 root = Configurator.isSystemRoot(dir);
166
167 } while (!(exists = fs.existsSync(pkg)) && !root);
168
1690 return exists ? pkg : undefined;
170 },
171
172
173 /**
174 * Create a JSON nconf store for the given file.
175 * @param file the file for which to create the JSON literal store.
176 * @returns {{type: string, store: *}}
177 */
178 _createJsonStore: function createJsonStore(file) {
1790 var contents;
180
1810 if (fs.existsSync(file)) {
182 // Minify the code to remove the comments
183 // NOTE: using fs.readFile instead of `require`
184 // so JSON parsing doesn't happen automatically.
1850 contents = fs.readFileSync(file, 'utf8');
1860 contents = JSON.minify(contents);
1870 if (typeof contents === 'string' && contents.length > 0) {
1880 try {
1890 contents = JSON.parse(contents);
1900 contents = this._resolver.resolve(contents);
191 } catch (e) {
1920 throw new Error(e + " at " + file);
193 }
1940 return {
195 type: 'literal',
196 store: contents
197 };
198 }
199 }
200
2010 return undefined;
202 }
203
204};
205
206
207
2081function getPort(nconf) {
2090 var value, port, ports;
210
2110 value = undefined;
2120 port = undefined;
2130 ports = nconf.get('port');
2140 ports = Array.isArray(ports) ? ports : [ ports ];
2150 ports.some(function (env) {
2160 value = (typeof env === 'number') ? env : nconf.get(env);
2170 port = parseInt(value, 10);
2180 port = isNaN(port) ? value : port;
2190 return !!port;
220 });
221
2220 return port;
223}
224
225
2261function getHost(nconf) {
2270 var host, hosts;
228
2290 if (typeof getPort(nconf) === 'string') {
2300 return undefined;
231 }
232
2330 host = undefined;
2340 hosts = nconf.get('host');
2350 hosts = Array.isArray(hosts) ? hosts : [ hosts ];
2360 hosts.some(function (env) {
2370 host = nconf.get(env);
2380 return !!host;
239 });
240
2410 return host;
242}
243
244
245
2461exports.create = function (appRoot) {
247
2480 nconf = new Configurator(appRoot)
249 .load(appRoot, ['app', 'middleware'])
250 .load(__dirname, ['webcore', 'middleware'])
251 .done();
252
2530 return Object.create(nconf, {
254 raw: {
255 get: function () {
2560 return Object.getPrototypeOf(this);
257 }
258 },
259
260 port: {
261 enumerable: true,
262 get: function () {
2630 return getPort(this);
264 }
265 },
266
267 host: {
268 enumerable: true,
269 get: function () {
2700 return getHost(this);
271 }
272 }
273 });
274};
275

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/util/index.js

50%
8
4
4
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
20
211exports.tryRequire = function tryRequire(moduleName, fallback) {
220 var result;
230 try {
240 result = moduleName && require(moduleName);
25 } catch (err) {
26 // noop
27 }
280 return result || fallback;
29};
30
31
321exports.configutil = require('./configutil');
33
34
351exports.pathutil = require('./pathutil');
36

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/lib/util/pathutil.js

21%
19
4
15
LineHitsSource
1/*───────────────────────────────────────────────────────────────────────────*\
2│ Copyright (C) 2014 eBay Software Foundation │
3│ │
4│hh ,'""`. │
5│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
6│ |(@)(@)| you may not use this file except in compliance with the License. │
7│ ) __ ( You may obtain a copy of the License at │
8│ /,'))((`.\ │
9│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
10│ `\ `)(' /' │
11│ │
12│ Unless required by applicable law or agreed to in writing, software │
13│ distributed under the License is distributed on an "AS IS" BASIS, │
14│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
15│ See the License for the specific language governing permissions and │
16│ limitations under the License. │
17\*───────────────────────────────────────────────────────────────────────────*/
181'use strict';
19
201var path = require('path');
21
22
231var proto = {
24
25 resolve: function () {
260 var args, segments, result;
27
280 args = Array.prototype.slice.call(arguments);
290 segments = args.reduce(function (prev, curr) {
300 if (curr !== undefined) {
310 if (!Array.isArray(curr)) {
320 curr = [curr];
33 }
340 return prev.concat(curr);
35 }
360 return prev;
37 }, []);
38
390 result = path.join.apply(null, segments);
400 if (path.resolve(result) === result) {
41 // already absolute path, so no need to use root
420 return result;
43 }
44
450 segments.unshift(this.root || (this.root = this._doResolve()));
460 return path.join.apply(null, segments);
47 }
48
49};
50
51
521exports.create = function (resolver) {
530 return Object.create(proto, {
54 root: {
55 value: undefined,
56 enumerable: true,
57 writable: true
58 },
59
60 _doResolve: {
610 value: resolver || function () { return process.cwd(); }
62 }
63 });
64};
65

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/node_modules/formidable/lib/file.js

23%
38
9
29
LineHitsSource
11if (global.GENTLY) require = GENTLY.hijack(require);
2
31var util = require('util'),
4 WriteStream = require('fs').WriteStream,
5 EventEmitter = require('events').EventEmitter,
6 crypto = require('crypto');
7
81function File(properties) {
90 EventEmitter.call(this);
10
110 this.size = 0;
120 this.path = null;
130 this.name = null;
140 this.type = null;
150 this.hash = null;
160 this.lastModifiedDate = null;
17
180 this._writeStream = null;
19
200 for (var key in properties) {
210 this[key] = properties[key];
22 }
23
240 if(typeof this.hash === 'string') {
250 this.hash = crypto.createHash(properties.hash);
26 } else {
270 this.hash = null;
28 }
29}
301module.exports = File;
311util.inherits(File, EventEmitter);
32
331File.prototype.open = function() {
340 this._writeStream = new WriteStream(this.path);
35};
36
371File.prototype.toJSON = function() {
380 return {
39 size: this.size,
40 path: this.path,
41 name: this.name,
42 type: this.type,
43 mtime: this.lastModifiedDate,
44 length: this.length,
45 filename: this.filename,
46 mime: this.mime
47 };
48};
49
501File.prototype.write = function(buffer, cb) {
510 var self = this;
520 if (self.hash) {
530 self.hash.update(buffer);
54 }
550 this._writeStream.write(buffer, function() {
560 self.lastModifiedDate = new Date();
570 self.size += buffer.length;
580 self.emit('progress', self.size);
590 cb();
60 });
61};
62
631File.prototype.end = function(cb) {
640 var self = this;
650 if (self.hash) {
660 self.hash = self.hash.digest('hex');
67 }
680 this._writeStream.end(function() {
690 self.emit('end');
700 cb();
71 });
72};
73

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/node_modules/formidable/lib/incoming_form.js

8%
280
25
255
LineHitsSource
11if (global.GENTLY) require = GENTLY.hijack(require);
2
31var fs = require('fs');
41var util = require('util'),
5 path = require('path'),
6 File = require('./file'),
7 MultipartParser = require('./multipart_parser').MultipartParser,
8 QuerystringParser = require('./querystring_parser').QuerystringParser,
9 OctetParser = require('./octet_parser').OctetParser,
10 JSONParser = require('./json_parser').JSONParser,
11 StringDecoder = require('string_decoder').StringDecoder,
12 EventEmitter = require('events').EventEmitter,
13 Stream = require('stream').Stream,
14 os = require('os');
15
161function IncomingForm(opts) {
170 if (!(this instanceof IncomingForm)) return new IncomingForm(opts);
180 EventEmitter.call(this);
19
200 opts=opts||{};
21
220 this.error = null;
230 this.ended = false;
24
250 this.maxFields = opts.maxFields || 1000;
260 this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024;
270 this.keepExtensions = opts.keepExtensions || false;
280 this.uploadDir = opts.uploadDir || os.tmpDir();
290 this.encoding = opts.encoding || 'utf-8';
300 this.headers = null;
310 this.type = null;
320 this.hash = false;
33
340 this.bytesReceived = null;
350 this.bytesExpected = null;
36
370 this._parser = null;
380 this._flushing = 0;
390 this._fieldsSize = 0;
400 this.openedFiles = [];
41
420 return this;
43};
441util.inherits(IncomingForm, EventEmitter);
451exports.IncomingForm = IncomingForm;
46
471IncomingForm.prototype.parse = function(req, cb) {
480 this.pause = function() {
490 try {
500 req.pause();
51 } catch (err) {
52 // the stream was destroyed
530 if (!this.ended) {
54 // before it was completed, crash & burn
550 this._error(err);
56 }
570 return false;
58 }
590 return true;
60 };
61
620 this.resume = function() {
630 try {
640 req.resume();
65 } catch (err) {
66 // the stream was destroyed
670 if (!this.ended) {
68 // before it was completed, crash & burn
690 this._error(err);
70 }
710 return false;
72 }
73
740 return true;
75 };
76
77 // Setup callback first, so we don't miss anything from data events emitted
78 // immediately.
790 if (cb) {
800 var fields = {}, files = {};
810 this
82 .on('field', function(name, value) {
830 fields[name] = value;
84 })
85 .on('file', function(name, file) {
860 files[name] = file;
87 })
88 .on('error', function(err) {
890 cb(err, fields, files);
90 })
91 .on('end', function() {
920 cb(null, fields, files);
93 });
94 }
95
96 // Parse headers and setup the parser, ready to start listening for data.
970 this.writeHeaders(req.headers);
98
99 // Start listening for data.
1000 var self = this;
1010 req
102 .on('error', function(err) {
1030 self._error(err);
104 })
105 .on('aborted', function() {
1060 self.emit('aborted');
1070 self._error(new Error('Request aborted'));
108 })
109 .on('data', function(buffer) {
1100 self.write(buffer);
111 })
112 .on('end', function() {
1130 if (self.error) {
1140 return;
115 }
116
1170 var err = self._parser.end();
1180 if (err) {
1190 self._error(err);
120 }
121 });
122
1230 return this;
124};
125
1261IncomingForm.prototype.writeHeaders = function(headers) {
1270 this.headers = headers;
1280 this._parseContentLength();
1290 this._parseContentType();
130};
131
1321IncomingForm.prototype.write = function(buffer) {
1330 if (!this._parser) {
1340 this._error(new Error('unintialized parser'));
1350 return;
136 }
137
1380 this.bytesReceived += buffer.length;
1390 this.emit('progress', this.bytesReceived, this.bytesExpected);
140
1410 var bytesParsed = this._parser.write(buffer);
1420 if (bytesParsed !== buffer.length) {
1430 this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed'));
144 }
145
1460 return bytesParsed;
147};
148
1491IncomingForm.prototype.pause = function() {
150 // this does nothing, unless overwritten in IncomingForm.parse
1510 return false;
152};
153
1541IncomingForm.prototype.resume = function() {
155 // this does nothing, unless overwritten in IncomingForm.parse
1560 return false;
157};
158
1591IncomingForm.prototype.onPart = function(part) {
160 // this method can be overwritten by the user
1610 this.handlePart(part);
162};
163
1641IncomingForm.prototype.handlePart = function(part) {
1650 var self = this;
166
1670 if (part.filename === undefined) {
1680 var value = ''
169 , decoder = new StringDecoder(this.encoding);
170
1710 part.on('data', function(buffer) {
1720 self._fieldsSize += buffer.length;
1730 if (self._fieldsSize > self.maxFieldsSize) {
1740 self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data'));
1750 return;
176 }
1770 value += decoder.write(buffer);
178 });
179
1800 part.on('end', function() {
1810 self.emit('field', part.name, value);
182 });
1830 return;
184 }
185
1860 this._flushing++;
187
1880 var file = new File({
189 path: this._uploadPath(part.filename),
190 name: part.filename,
191 type: part.mime,
192 hash: self.hash
193 });
194
1950 this.emit('fileBegin', part.name, file);
196
1970 file.open();
1980 this.openedFiles.push(file);
199
2000 part.on('data', function(buffer) {
2010 self.pause();
2020 file.write(buffer, function() {
2030 self.resume();
204 });
205 });
206
2070 part.on('end', function() {
2080 file.end(function() {
2090 self._flushing--;
2100 self.emit('file', part.name, file);
2110 self._maybeEnd();
212 });
213 });
214};
215
2161function dummyParser(self) {
2170 return {
218 end: function () {
2190 self.ended = true;
2200 self._maybeEnd();
2210 return null;
222 }
223 };
224}
225
2261IncomingForm.prototype._parseContentType = function() {
2270 if (this.bytesExpected === 0) {
2280 this._parser = dummyParser(this);
2290 return;
230 }
231
2320 if (!this.headers['content-type']) {
2330 this._error(new Error('bad content-type header, no content-type'));
2340 return;
235 }
236
2370 if (this.headers['content-type'].match(/octet-stream/i)) {
2380 this._initOctetStream();
2390 return;
240 }
241
2420 if (this.headers['content-type'].match(/urlencoded/i)) {
2430 this._initUrlencoded();
2440 return;
245 }
246
2470 if (this.headers['content-type'].match(/multipart/i)) {
2480 var m;
2490 if (m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i)) {
2500 this._initMultipart(m[1] || m[2]);
251 } else {
2520 this._error(new Error('bad content-type header, no multipart boundary'));
253 }
2540 return;
255 }
256
2570 if (this.headers['content-type'].match(/json/i)) {
2580 this._initJSONencoded();
2590 return;
260 }
261
2620 this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type']));
263};
264
2651IncomingForm.prototype._error = function(err) {
2660 if (this.error || this.ended) {
2670 return;
268 }
269
2700 this.error = err;
2710 this.pause();
2720 this.emit('error', err);
273
2740 if (Array.isArray(this.openedFiles)) {
2750 this.openedFiles.forEach(function(file) {
2760 file._writeStream.destroy();
2770 setTimeout(fs.unlink, 0, file.path);
278 });
279 }
280};
281
2821IncomingForm.prototype._parseContentLength = function() {
2830 this.bytesReceived = 0;
2840 if (this.headers['content-length']) {
2850 this.bytesExpected = parseInt(this.headers['content-length'], 10);
2860 } else if (this.headers['transfer-encoding'] === undefined) {
2870 this.bytesExpected = 0;
288 }
289
2900 if (this.bytesExpected !== null) {
2910 this.emit('progress', this.bytesReceived, this.bytesExpected);
292 }
293};
294
2951IncomingForm.prototype._newParser = function() {
2960 return new MultipartParser();
297};
298
2991IncomingForm.prototype._initMultipart = function(boundary) {
3000 this.type = 'multipart';
301
3020 var parser = new MultipartParser(),
303 self = this,
304 headerField,
305 headerValue,
306 part;
307
3080 parser.initWithBoundary(boundary);
309
3100 parser.onPartBegin = function() {
3110 part = new Stream();
3120 part.readable = true;
3130 part.headers = {};
3140 part.name = null;
3150 part.filename = null;
3160 part.mime = null;
317
3180 part.transferEncoding = 'binary';
3190 part.transferBuffer = '';
320
3210 headerField = '';
3220 headerValue = '';
323 };
324
3250 parser.onHeaderField = function(b, start, end) {
3260 headerField += b.toString(self.encoding, start, end);
327 };
328
3290 parser.onHeaderValue = function(b, start, end) {
3300 headerValue += b.toString(self.encoding, start, end);
331 };
332
3330 parser.onHeaderEnd = function() {
3340 headerField = headerField.toLowerCase();
3350 part.headers[headerField] = headerValue;
336
3370 var m;
3380 if (headerField == 'content-disposition') {
3390 if (m = headerValue.match(/\bname="([^"]+)"/i)) {
3400 part.name = m[1];
341 }
342
3430 part.filename = self._fileName(headerValue);
3440 } else if (headerField == 'content-type') {
3450 part.mime = headerValue;
3460 } else if (headerField == 'content-transfer-encoding') {
3470 part.transferEncoding = headerValue.toLowerCase();
348 }
349
3500 headerField = '';
3510 headerValue = '';
352 };
353
3540 parser.onHeadersEnd = function() {
3550 switch(part.transferEncoding){
356 case 'binary':
357 case '7bit':
358 case '8bit':
3590 parser.onPartData = function(b, start, end) {
3600 part.emit('data', b.slice(start, end));
361 };
362
3630 parser.onPartEnd = function() {
3640 part.emit('end');
365 };
3660 break;
367
368 case 'base64':
3690 parser.onPartData = function(b, start, end) {
3700 part.transferBuffer += b.slice(start, end).toString('ascii');
371
372 /*
373 four bytes (chars) in base64 converts to three bytes in binary
374 encoding. So we should always work with a number of bytes that
375 can be divided by 4, it will result in a number of buytes that
376 can be divided vy 3.
377 */
3780 var offset = parseInt(part.transferBuffer.length / 4) * 4;
3790 part.emit('data', new Buffer(part.transferBuffer.substring(0, offset), 'base64'))
3800 part.transferBuffer = part.transferBuffer.substring(offset);
381 };
382
3830 parser.onPartEnd = function() {
3840 part.emit('data', new Buffer(part.transferBuffer, 'base64'))
3850 part.emit('end');
386 };
3870 break;
388
389 default:
3900 return self._error(new Error('unknown transfer-encoding'));
391 }
392
3930 self.onPart(part);
394 };
395
396
3970 parser.onEnd = function() {
3980 self.ended = true;
3990 self._maybeEnd();
400 };
401
4020 this._parser = parser;
403};
404
4051IncomingForm.prototype._fileName = function(headerValue) {
4060 var m = headerValue.match(/\bfilename="(.*?)"($|; )/i);
4070 if (!m) return;
408
4090 var filename = m[1].substr(m[1].lastIndexOf('\\') + 1);
4100 filename = filename.replace(/%22/g, '"');
4110 filename = filename.replace(/&#([\d]{4});/g, function(m, code) {
4120 return String.fromCharCode(code);
413 });
4140 return filename;
415};
416
4171IncomingForm.prototype._initUrlencoded = function() {
4180 this.type = 'urlencoded';
419
4200 var parser = new QuerystringParser(this.maxFields)
421 , self = this;
422
4230 parser.onField = function(key, val) {
4240 self.emit('field', key, val);
425 };
426
4270 parser.onEnd = function() {
4280 self.ended = true;
4290 self._maybeEnd();
430 };
431
4320 this._parser = parser;
433};
434
4351IncomingForm.prototype._initOctetStream = function() {
4360 this.type = 'octet-stream';
4370 var filename = this.headers['x-file-name'];
4380 var mime = this.headers['content-type'];
439
4400 var file = new File({
441 path: this._uploadPath(filename),
442 name: filename,
443 type: mime
444 });
445
4460 file.open();
447
4480 this.emit('fileBegin', filename, file);
449
4500 this._flushing++;
451
4520 var self = this;
453
4540 self._parser = new OctetParser();
455
456 //Keep track of writes that haven't finished so we don't emit the file before it's done being written
4570 var outstandingWrites = 0;
458
4590 self._parser.on('data', function(buffer){
4600 self.pause();
4610 outstandingWrites++;
462
4630 file.write(buffer, function() {
4640 outstandingWrites--;
4650 self.resume();
466
4670 if(self.ended){
4680 self._parser.emit('doneWritingFile');
469 }
470 });
471 });
472
4730 self._parser.on('end', function(){
4740 self._flushing--;
4750 self.ended = true;
476
4770 var done = function(){
4780 self.emit('file', 'file', file);
4790 self._maybeEnd();
480 };
481
4820 if(outstandingWrites === 0){
4830 done();
484 } else {
4850 self._parser.once('doneWritingFile', done);
486 }
487 });
488};
489
4901IncomingForm.prototype._initJSONencoded = function() {
4910 this.type = 'json';
492
4930 var parser = new JSONParser()
494 , self = this;
495
4960 if (this.bytesExpected) {
4970 parser.initWithLength(this.bytesExpected);
498 }
499
5000 parser.onField = function(key, val) {
5010 self.emit('field', key, val);
502 }
503
5040 parser.onEnd = function() {
5050 self.ended = true;
5060 self._maybeEnd();
507 };
508
5090 this._parser = parser;
510};
511
5121IncomingForm.prototype._uploadPath = function(filename) {
5130 var name = '';
5140 for (var i = 0; i < 32; i++) {
5150 name += Math.floor(Math.random() * 16).toString(16);
516 }
517
5180 if (this.keepExtensions) {
5190 var ext = path.extname(filename);
5200 ext = ext.replace(/(\.[a-z0-9]+).*/, '$1');
521
5220 name += ext;
523 }
524
5250 return path.join(this.uploadDir, name);
526};
527
5281IncomingForm.prototype._maybeEnd = function() {
5290 if (!this.ended || this._flushing || this.error) {
5300 return;
531 }
532
5330 this.emit('end');
534};
535
536

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/node_modules/formidable/lib/index.js

100%
3
3
0
LineHitsSource
11var IncomingForm = require('./incoming_form').IncomingForm;
21IncomingForm.IncomingForm = IncomingForm;
31module.exports = IncomingForm;
4

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/node_modules/formidable/lib/json_parser.js

33%
21
7
14
LineHitsSource
11if (global.GENTLY) require = GENTLY.hijack(require);
2
31var Buffer = require('buffer').Buffer
4
51function JSONParser() {
60 this.data = new Buffer('');
70 this.bytesWritten = 0;
8};
91exports.JSONParser = JSONParser;
10
111JSONParser.prototype.initWithLength = function(length) {
120 this.data = new Buffer(length);
13}
14
151JSONParser.prototype.write = function(buffer) {
160 if (this.data.length >= this.bytesWritten + buffer.length) {
170 buffer.copy(this.data, this.bytesWritten);
18 } else {
190 this.data = Buffer.concat([this.data, buffer]);
20 }
210 this.bytesWritten += buffer.length;
220 return buffer.length;
23}
24
251JSONParser.prototype.end = function() {
260 try {
270 var fields = JSON.parse(this.data.toString('utf8'))
280 for (var field in fields) {
290 this.onField(field, fields[field]);
30 }
31 } catch (e) {}
320 this.data = null;
33
340 this.onEnd();
35}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/node_modules/formidable/lib/multipart_parser.js

5%
170
10
160
LineHitsSource
11var Buffer = require('buffer').Buffer,
2 s = 0,
3 S =
4 { PARSER_UNINITIALIZED: s++,
5 START: s++,
6 START_BOUNDARY: s++,
7 HEADER_FIELD_START: s++,
8 HEADER_FIELD: s++,
9 HEADER_VALUE_START: s++,
10 HEADER_VALUE: s++,
11 HEADER_VALUE_ALMOST_DONE: s++,
12 HEADERS_ALMOST_DONE: s++,
13 PART_DATA_START: s++,
14 PART_DATA: s++,
15 PART_END: s++,
16 END: s++
17 },
18
19 f = 1,
20 F =
21 { PART_BOUNDARY: f,
22 LAST_BOUNDARY: f *= 2
23 },
24
25 LF = 10,
26 CR = 13,
27 SPACE = 32,
28 HYPHEN = 45,
29 COLON = 58,
30 A = 97,
31 Z = 122,
32
33 lower = function(c) {
340 return c | 0x20;
35 };
36
371for (s in S) {
3813 exports[s] = S[s];
39}
40
411function MultipartParser() {
420 this.boundary = null;
430 this.boundaryChars = null;
440 this.lookbehind = null;
450 this.state = S.PARSER_UNINITIALIZED;
46
470 this.index = null;
480 this.flags = 0;
49};
501exports.MultipartParser = MultipartParser;
51
521MultipartParser.stateToString = function(stateNumber) {
530 for (var state in S) {
540 var number = S[state];
550 if (number === stateNumber) return state;
56 }
57};
58
591MultipartParser.prototype.initWithBoundary = function(str) {
600 this.boundary = new Buffer(str.length+4);
610 this.boundary.write('\r\n--', 'ascii', 0);
620 this.boundary.write(str, 'ascii', 4);
630 this.lookbehind = new Buffer(this.boundary.length+8);
640 this.state = S.START;
65
660 this.boundaryChars = {};
670 for (var i = 0; i < this.boundary.length; i++) {
680 this.boundaryChars[this.boundary[i]] = true;
69 }
70};
71
721MultipartParser.prototype.write = function(buffer) {
730 var self = this,
74 i = 0,
75 len = buffer.length,
76 prevIndex = this.index,
77 index = this.index,
78 state = this.state,
79 flags = this.flags,
80 lookbehind = this.lookbehind,
81 boundary = this.boundary,
82 boundaryChars = this.boundaryChars,
83 boundaryLength = this.boundary.length,
84 boundaryEnd = boundaryLength - 1,
85 bufferLength = buffer.length,
86 c,
87 cl,
88
89 mark = function(name) {
900 self[name+'Mark'] = i;
91 },
92 clear = function(name) {
930 delete self[name+'Mark'];
94 },
95 callback = function(name, buffer, start, end) {
960 if (start !== undefined && start === end) {
970 return;
98 }
99
1000 var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
1010 if (callbackSymbol in self) {
1020 self[callbackSymbol](buffer, start, end);
103 }
104 },
105 dataCallback = function(name, clear) {
1060 var markSymbol = name+'Mark';
1070 if (!(markSymbol in self)) {
1080 return;
109 }
110
1110 if (!clear) {
1120 callback(name, buffer, self[markSymbol], buffer.length);
1130 self[markSymbol] = 0;
114 } else {
1150 callback(name, buffer, self[markSymbol], i);
1160 delete self[markSymbol];
117 }
118 };
119
1200 for (i = 0; i < len; i++) {
1210 c = buffer[i];
1220 switch (state) {
123 case S.PARSER_UNINITIALIZED:
1240 return i;
125 case S.START:
1260 index = 0;
1270 state = S.START_BOUNDARY;
128 case S.START_BOUNDARY:
1290 if (index == boundary.length - 2) {
1300 if (c != CR) {
1310 return i;
132 }
1330 index++;
1340 break;
1350 } else if (index - 1 == boundary.length - 2) {
1360 if (c != LF) {
1370 return i;
138 }
1390 index = 0;
1400 callback('partBegin');
1410 state = S.HEADER_FIELD_START;
1420 break;
143 }
144
1450 if (c != boundary[index+2]) {
1460 index = -2;
147 }
1480 if (c == boundary[index+2]) {
1490 index++;
150 }
1510 break;
152 case S.HEADER_FIELD_START:
1530 state = S.HEADER_FIELD;
1540 mark('headerField');
1550 index = 0;
156 case S.HEADER_FIELD:
1570 if (c == CR) {
1580 clear('headerField');
1590 state = S.HEADERS_ALMOST_DONE;
1600 break;
161 }
162
1630 index++;
1640 if (c == HYPHEN) {
1650 break;
166 }
167
1680 if (c == COLON) {
1690 if (index == 1) {
170 // empty header field
1710 return i;
172 }
1730 dataCallback('headerField', true);
1740 state = S.HEADER_VALUE_START;
1750 break;
176 }
177
1780 cl = lower(c);
1790 if (cl < A || cl > Z) {
1800 return i;
181 }
1820 break;
183 case S.HEADER_VALUE_START:
1840 if (c == SPACE) {
1850 break;
186 }
187
1880 mark('headerValue');
1890 state = S.HEADER_VALUE;
190 case S.HEADER_VALUE:
1910 if (c == CR) {
1920 dataCallback('headerValue', true);
1930 callback('headerEnd');
1940 state = S.HEADER_VALUE_ALMOST_DONE;
195 }
1960 break;
197 case S.HEADER_VALUE_ALMOST_DONE:
1980 if (c != LF) {
1990 return i;
200 }
2010 state = S.HEADER_FIELD_START;
2020 break;
203 case S.HEADERS_ALMOST_DONE:
2040 if (c != LF) {
2050 return i;
206 }
207
2080 callback('headersEnd');
2090 state = S.PART_DATA_START;
2100 break;
211 case S.PART_DATA_START:
2120 state = S.PART_DATA;
2130 mark('partData');
214 case S.PART_DATA:
2150 prevIndex = index;
216
2170 if (index == 0) {
218 // boyer-moore derrived algorithm to safely skip non-boundary data
2190 i += boundaryEnd;
2200 while (i < bufferLength && !(buffer[i] in boundaryChars)) {
2210 i += boundaryLength;
222 }
2230 i -= boundaryEnd;
2240 c = buffer[i];
225 }
226
2270 if (index < boundary.length) {
2280 if (boundary[index] == c) {
2290 if (index == 0) {
2300 dataCallback('partData', true);
231 }
2320 index++;
233 } else {
2340 index = 0;
235 }
2360 } else if (index == boundary.length) {
2370 index++;
2380 if (c == CR) {
239 // CR = part boundary
2400 flags |= F.PART_BOUNDARY;
2410 } else if (c == HYPHEN) {
242 // HYPHEN = end boundary
2430 flags |= F.LAST_BOUNDARY;
244 } else {
2450 index = 0;
246 }
2470 } else if (index - 1 == boundary.length) {
2480 if (flags & F.PART_BOUNDARY) {
2490 index = 0;
2500 if (c == LF) {
251 // unset the PART_BOUNDARY flag
2520 flags &= ~F.PART_BOUNDARY;
2530 callback('partEnd');
2540 callback('partBegin');
2550 state = S.HEADER_FIELD_START;
2560 break;
257 }
2580 } else if (flags & F.LAST_BOUNDARY) {
2590 if (c == HYPHEN) {
2600 callback('partEnd');
2610 callback('end');
2620 state = S.END;
263 } else {
2640 index = 0;
265 }
266 } else {
2670 index = 0;
268 }
269 }
270
2710 if (index > 0) {
272 // when matching a possible boundary, keep a lookbehind reference
273 // in case it turns out to be a false lead
2740 lookbehind[index-1] = c;
2750 } else if (prevIndex > 0) {
276 // if our boundary turned out to be rubbish, the captured lookbehind
277 // belongs to partData
2780 callback('partData', lookbehind, 0, prevIndex);
2790 prevIndex = 0;
2800 mark('partData');
281
282 // reconsider the current character even so it interrupted the sequence
283 // it could be the beginning of a new sequence
2840 i--;
285 }
286
2870 break;
288 case S.END:
2890 break;
290 default:
2910 return i;
292 }
293 }
294
2950 dataCallback('headerField');
2960 dataCallback('headerValue');
2970 dataCallback('partData');
298
2990 this.index = index;
3000 this.state = state;
3010 this.flags = flags;
302
3030 return len;
304};
305
3061MultipartParser.prototype.end = function() {
3070 var callback = function(self, name) {
3080 var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
3090 if (callbackSymbol in self) {
3100 self[callbackSymbol]();
311 }
312 };
3130 if ((this.state == S.HEADER_FIELD_START && this.index == 0) ||
314 (this.state == S.PART_DATA && this.index == this.boundary.length)) {
3150 callback(this, 'partEnd');
3160 callback(this, 'end');
3170 } else if (this.state != S.END) {
3180 return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain());
319 }
320};
321
3221MultipartParser.prototype.explain = function() {
3230 return 'state = ' + MultipartParser.stateToString(this.state);
324};
325

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/node_modules/formidable/lib/octet_parser.js

54%
11
6
5
LineHitsSource
11var EventEmitter = require('events').EventEmitter
2 , util = require('util');
3
41function OctetParser(options){
50 if(!(this instanceof OctetParser)) return new OctetParser(options);
60 EventEmitter.call(this);
7}
8
91util.inherits(OctetParser, EventEmitter);
10
111exports.OctetParser = OctetParser;
12
131OctetParser.prototype.write = function(buffer) {
140 this.emit('data', buffer);
150 return buffer.length;
16};
17
181OctetParser.prototype.end = function() {
190 this.emit('end');
20};
21

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/node_modules/formidable/lib/querystring_parser.js

40%
15
6
9
LineHitsSource
11if (global.GENTLY) require = GENTLY.hijack(require);
2
3// This is a buffering parser, not quite as nice as the multipart one.
4// If I find time I'll rewrite this to be fully streaming as well
51var querystring = require('querystring');
6
71function QuerystringParser(maxKeys) {
80 this.maxKeys = maxKeys;
90 this.buffer = '';
10};
111exports.QuerystringParser = QuerystringParser;
12
131QuerystringParser.prototype.write = function(buffer) {
140 this.buffer += buffer.toString('ascii');
150 return buffer.length;
16};
17
181QuerystringParser.prototype.end = function() {
190 var fields = querystring.parse(this.buffer, '&', '=', { maxKeys: this.maxKeys });
200 for (var field in fields) {
210 this.onField(field, fields[field]);
22 }
230 this.buffer = '';
24
250 this.onEnd();
26};
27
28

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/node_modules/kraken-devtools/node_modules/async/lib/async.js

16%
535
87
448
LineHitsSource
1/*global setImmediate: false, setTimeout: false, console: false */
21(function () {
3
41 var async = {};
5
6 // global on the server, window in the browser
71 var root, previous_async;
8
91 root = this;
101 if (root != null) {
111 previous_async = root.async;
12 }
13
141 async.noConflict = function () {
150 root.async = previous_async;
160 return async;
17 };
18
191 function only_once(fn) {
200 var called = false;
210 return function() {
220 if (called) throw new Error("Callback was already called.");
230 called = true;
240 fn.apply(root, arguments);
25 }
26 }
27
28 //// cross-browser compatiblity functions ////
29
301 var _each = function (arr, iterator) {
310 if (arr.forEach) {
320 return arr.forEach(iterator);
33 }
340 for (var i = 0; i < arr.length; i += 1) {
350 iterator(arr[i], i, arr);
36 }
37 };
38
391 var _map = function (arr, iterator) {
400 if (arr.map) {
410 return arr.map(iterator);
42 }
430 var results = [];
440 _each(arr, function (x, i, a) {
450 results.push(iterator(x, i, a));
46 });
470 return results;
48 };
49
501 var _reduce = function (arr, iterator, memo) {
510 if (arr.reduce) {
520 return arr.reduce(iterator, memo);
53 }
540 _each(arr, function (x, i, a) {
550 memo = iterator(memo, x, i, a);
56 });
570 return memo;
58 };
59
601 var _keys = function (obj) {
610 if (Object.keys) {
620 return Object.keys(obj);
63 }
640 var keys = [];
650 for (var k in obj) {
660 if (obj.hasOwnProperty(k)) {
670 keys.push(k);
68 }
69 }
700 return keys;
71 };
72
73 //// exported async module functions ////
74
75 //// nextTick implementation with browser-compatible fallback ////
761 if (typeof process === 'undefined' || !(process.nextTick)) {
770 if (typeof setImmediate === 'function') {
780 async.nextTick = function (fn) {
79 // not a direct alias for IE10 compatibility
800 setImmediate(fn);
81 };
820 async.setImmediate = async.nextTick;
83 }
84 else {
850 async.nextTick = function (fn) {
860 setTimeout(fn, 0);
87 };
880 async.setImmediate = async.nextTick;
89 }
90 }
91 else {
921 async.nextTick = process.nextTick;
931 if (typeof setImmediate !== 'undefined') {
941 async.setImmediate = function (fn) {
95 // not a direct alias for IE10 compatibility
960 setImmediate(fn);
97 };
98 }
99 else {
1000 async.setImmediate = async.nextTick;
101 }
102 }
103
1041 async.each = function (arr, iterator, callback) {
1050 callback = callback || function () {};
1060 if (!arr.length) {
1070 return callback();
108 }
1090 var completed = 0;
1100 _each(arr, function (x) {
1110 iterator(x, only_once(function (err) {
1120 if (err) {
1130 callback(err);
1140 callback = function () {};
115 }
116 else {
1170 completed += 1;
1180 if (completed >= arr.length) {
1190 callback(null);
120 }
121 }
122 }));
123 });
124 };
1251 async.forEach = async.each;
126
1271 async.eachSeries = function (arr, iterator, callback) {
1280 callback = callback || function () {};
1290 if (!arr.length) {
1300 return callback();
131 }
1320 var completed = 0;
1330 var iterate = function () {
1340 iterator(arr[completed], function (err) {
1350 if (err) {
1360 callback(err);
1370 callback = function () {};
138 }
139 else {
1400 completed += 1;
1410 if (completed >= arr.length) {
1420 callback(null);
143 }
144 else {
1450 iterate();
146 }
147 }
148 });
149 };
1500 iterate();
151 };
1521 async.forEachSeries = async.eachSeries;
153
1541 async.eachLimit = function (arr, limit, iterator, callback) {
1550 var fn = _eachLimit(limit);
1560 fn.apply(null, [arr, iterator, callback]);
157 };
1581 async.forEachLimit = async.eachLimit;
159
1601 var _eachLimit = function (limit) {
161
1620 return function (arr, iterator, callback) {
1630 callback = callback || function () {};
1640 if (!arr.length || limit <= 0) {
1650 return callback();
166 }
1670 var completed = 0;
1680 var started = 0;
1690 var running = 0;
170
1710 (function replenish () {
1720 if (completed >= arr.length) {
1730 return callback();
174 }
175
1760 while (running < limit && started < arr.length) {
1770 started += 1;
1780 running += 1;
1790 iterator(arr[started - 1], function (err) {
1800 if (err) {
1810 callback(err);
1820 callback = function () {};
183 }
184 else {
1850 completed += 1;
1860 running -= 1;
1870 if (completed >= arr.length) {
1880 callback();
189 }
190 else {
1910 replenish();
192 }
193 }
194 });
195 }
196 })();
197 };
198 };
199
200
2011 var doParallel = function (fn) {
2026 return function () {
2030 var args = Array.prototype.slice.call(arguments);
2040 return fn.apply(null, [async.each].concat(args));
205 };
206 };
2071 var doParallelLimit = function(limit, fn) {
2080 return function () {
2090 var args = Array.prototype.slice.call(arguments);
2100 return fn.apply(null, [_eachLimit(limit)].concat(args));
211 };
212 };
2131 var doSeries = function (fn) {
2146 return function () {
2150 var args = Array.prototype.slice.call(arguments);
2160 return fn.apply(null, [async.eachSeries].concat(args));
217 };
218 };
219
220
2211 var _asyncMap = function (eachfn, arr, iterator, callback) {
2220 var results = [];
2230 arr = _map(arr, function (x, i) {
2240 return {index: i, value: x};
225 });
2260 eachfn(arr, function (x, callback) {
2270 iterator(x.value, function (err, v) {
2280 results[x.index] = v;
2290 callback(err);
230 });
231 }, function (err) {
2320 callback(err, results);
233 });
234 };
2351 async.map = doParallel(_asyncMap);
2361 async.mapSeries = doSeries(_asyncMap);
2371 async.mapLimit = function (arr, limit, iterator, callback) {
2380 return _mapLimit(limit)(arr, iterator, callback);
239 };
240
2411 var _mapLimit = function(limit) {
2420 return doParallelLimit(limit, _asyncMap);
243 };
244
245 // reduce only has a series version, as doing reduce in parallel won't
246 // work in many situations.
2471 async.reduce = function (arr, memo, iterator, callback) {
2480 async.eachSeries(arr, function (x, callback) {
2490 iterator(memo, x, function (err, v) {
2500 memo = v;
2510 callback(err);
252 });
253 }, function (err) {
2540 callback(err, memo);
255 });
256 };
257 // inject alias
2581 async.inject = async.reduce;
259 // foldl alias
2601 async.foldl = async.reduce;
261
2621 async.reduceRight = function (arr, memo, iterator, callback) {
2630 var reversed = _map(arr, function (x) {
2640 return x;
265 }).reverse();
2660 async.reduce(reversed, memo, iterator, callback);
267 };
268 // foldr alias
2691 async.foldr = async.reduceRight;
270
2711 var _filter = function (eachfn, arr, iterator, callback) {
2720 var results = [];
2730 arr = _map(arr, function (x, i) {
2740 return {index: i, value: x};
275 });
2760 eachfn(arr, function (x, callback) {
2770 iterator(x.value, function (v) {
2780 if (v) {
2790 results.push(x);
280 }
2810 callback();
282 });
283 }, function (err) {
2840 callback(_map(results.sort(function (a, b) {
2850 return a.index - b.index;
286 }), function (x) {
2870 return x.value;
288 }));
289 });
290 };
2911 async.filter = doParallel(_filter);
2921 async.filterSeries = doSeries(_filter);
293 // select alias
2941 async.select = async.filter;
2951 async.selectSeries = async.filterSeries;
296
2971 var _reject = function (eachfn, arr, iterator, callback) {
2980 var results = [];
2990 arr = _map(arr, function (x, i) {
3000 return {index: i, value: x};
301 });
3020 eachfn(arr, function (x, callback) {
3030 iterator(x.value, function (v) {
3040 if (!v) {
3050 results.push(x);
306 }
3070 callback();
308 });
309 }, function (err) {
3100 callback(_map(results.sort(function (a, b) {
3110 return a.index - b.index;
312 }), function (x) {
3130 return x.value;
314 }));
315 });
316 };
3171 async.reject = doParallel(_reject);
3181 async.rejectSeries = doSeries(_reject);
319
3201 var _detect = function (eachfn, arr, iterator, main_callback) {
3210 eachfn(arr, function (x, callback) {
3220 iterator(x, function (result) {
3230 if (result) {
3240 main_callback(x);
3250 main_callback = function () {};
326 }
327 else {
3280 callback();
329 }
330 });
331 }, function (err) {
3320 main_callback();
333 });
334 };
3351 async.detect = doParallel(_detect);
3361 async.detectSeries = doSeries(_detect);
337
3381 async.some = function (arr, iterator, main_callback) {
3390 async.each(arr, function (x, callback) {
3400 iterator(x, function (v) {
3410 if (v) {
3420 main_callback(true);
3430 main_callback = function () {};
344 }
3450 callback();
346 });
347 }, function (err) {
3480 main_callback(false);
349 });
350 };
351 // any alias
3521 async.any = async.some;
353
3541 async.every = function (arr, iterator, main_callback) {
3550 async.each(arr, function (x, callback) {
3560 iterator(x, function (v) {
3570 if (!v) {
3580 main_callback(false);
3590 main_callback = function () {};
360 }
3610 callback();
362 });
363 }, function (err) {
3640 main_callback(true);
365 });
366 };
367 // all alias
3681 async.all = async.every;
369
3701 async.sortBy = function (arr, iterator, callback) {
3710 async.map(arr, function (x, callback) {
3720 iterator(x, function (err, criteria) {
3730 if (err) {
3740 callback(err);
375 }
376 else {
3770 callback(null, {value: x, criteria: criteria});
378 }
379 });
380 }, function (err, results) {
3810 if (err) {
3820 return callback(err);
383 }
384 else {
3850 var fn = function (left, right) {
3860 var a = left.criteria, b = right.criteria;
3870 return a < b ? -1 : a > b ? 1 : 0;
388 };
3890 callback(null, _map(results.sort(fn), function (x) {
3900 return x.value;
391 }));
392 }
393 });
394 };
395
3961 async.auto = function (tasks, callback) {
3970 callback = callback || function () {};
3980 var keys = _keys(tasks);
3990 if (!keys.length) {
4000 return callback(null);
401 }
402
4030 var results = {};
404
4050 var listeners = [];
4060 var addListener = function (fn) {
4070 listeners.unshift(fn);
408 };
4090 var removeListener = function (fn) {
4100 for (var i = 0; i < listeners.length; i += 1) {
4110 if (listeners[i] === fn) {
4120 listeners.splice(i, 1);
4130 return;
414 }
415 }
416 };
4170 var taskComplete = function () {
4180 _each(listeners.slice(0), function (fn) {
4190 fn();
420 });
421 };
422
4230 addListener(function () {
4240 if (_keys(results).length === keys.length) {
4250 callback(null, results);
4260 callback = function () {};
427 }
428 });
429
4300 _each(keys, function (k) {
4310 var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
4320 var taskCallback = function (err) {
4330 var args = Array.prototype.slice.call(arguments, 1);
4340 if (args.length <= 1) {
4350 args = args[0];
436 }
4370 if (err) {
4380 var safeResults = {};
4390 _each(_keys(results), function(rkey) {
4400 safeResults[rkey] = results[rkey];
441 });
4420 safeResults[k] = args;
4430 callback(err, safeResults);
444 // stop subsequent errors hitting callback multiple times
4450 callback = function () {};
446 }
447 else {
4480 results[k] = args;
4490 async.setImmediate(taskComplete);
450 }
451 };
4520 var requires = task.slice(0, Math.abs(task.length - 1)) || [];
4530 var ready = function () {
4540 return _reduce(requires, function (a, x) {
4550 return (a && results.hasOwnProperty(x));
456 }, true) && !results.hasOwnProperty(k);
457 };
4580 if (ready()) {
4590 task[task.length - 1](taskCallback, results);
460 }
461 else {
4620 var listener = function () {
4630 if (ready()) {
4640 removeListener(listener);
4650 task[task.length - 1](taskCallback, results);
466 }
467 };
4680 addListener(listener);
469 }
470 });
471 };
472
4731 async.waterfall = function (tasks, callback) {
4740 callback = callback || function () {};
4750 if (tasks.constructor !== Array) {
4760 var err = new Error('First argument to waterfall must be an array of functions');
4770 return callback(err);
478 }
4790 if (!tasks.length) {
4800 return callback();
481 }
4820 var wrapIterator = function (iterator) {
4830 return function (err) {
4840 if (err) {
4850 callback.apply(null, arguments);
4860 callback = function () {};
487 }
488 else {
4890 var args = Array.prototype.slice.call(arguments, 1);
4900 var next = iterator.next();
4910 if (next) {
4920 args.push(wrapIterator(next));
493 }
494 else {
4950 args.push(callback);
496 }
4970 async.setImmediate(function () {
4980 iterator.apply(null, args);
499 });
500 }
501 };
502 };
5030 wrapIterator(async.iterator(tasks))();
504 };
505
5061 var _parallel = function(eachfn, tasks, callback) {
5070 callback = callback || function () {};
5080 if (tasks.constructor === Array) {
5090 eachfn.map(tasks, function (fn, callback) {
5100 if (fn) {
5110 fn(function (err) {
5120 var args = Array.prototype.slice.call(arguments, 1);
5130 if (args.length <= 1) {
5140 args = args[0];
515 }
5160 callback.call(null, err, args);
517 });
518 }
519 }, callback);
520 }
521 else {
5220 var results = {};
5230 eachfn.each(_keys(tasks), function (k, callback) {
5240 tasks[k](function (err) {
5250 var args = Array.prototype.slice.call(arguments, 1);
5260 if (args.length <= 1) {
5270 args = args[0];
528 }
5290 results[k] = args;
5300 callback(err);
531 });
532 }, function (err) {
5330 callback(err, results);
534 });
535 }
536 };
537
5381 async.parallel = function (tasks, callback) {
5390 _parallel({ map: async.map, each: async.each }, tasks, callback);
540 };
541
5421 async.parallelLimit = function(tasks, limit, callback) {
5430 _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
544 };
545
5461 async.series = function (tasks, callback) {
5470 callback = callback || function () {};
5480 if (tasks.constructor === Array) {
5490 async.mapSeries(tasks, function (fn, callback) {
5500 if (fn) {
5510 fn(function (err) {
5520 var args = Array.prototype.slice.call(arguments, 1);
5530 if (args.length <= 1) {
5540 args = args[0];
555 }
5560 callback.call(null, err, args);
557 });
558 }
559 }, callback);
560 }
561 else {
5620 var results = {};
5630 async.eachSeries(_keys(tasks), function (k, callback) {
5640 tasks[k](function (err) {
5650 var args = Array.prototype.slice.call(arguments, 1);
5660 if (args.length <= 1) {
5670 args = args[0];
568 }
5690 results[k] = args;
5700 callback(err);
571 });
572 }, function (err) {
5730 callback(err, results);
574 });
575 }
576 };
577
5781 async.iterator = function (tasks) {
5790 var makeCallback = function (index) {
5800 var fn = function () {
5810 if (tasks.length) {
5820 tasks[index].apply(null, arguments);
583 }
5840 return fn.next();
585 };
5860 fn.next = function () {
5870 return (index < tasks.length - 1) ? makeCallback(index + 1): null;
588 };
5890 return fn;
590 };
5910 return makeCallback(0);
592 };
593
5941 async.apply = function (fn) {
5950 var args = Array.prototype.slice.call(arguments, 1);
5960 return function () {
5970 return fn.apply(
598 null, args.concat(Array.prototype.slice.call(arguments))
599 );
600 };
601 };
602
6031 var _concat = function (eachfn, arr, fn, callback) {
6040 var r = [];
6050 eachfn(arr, function (x, cb) {
6060 fn(x, function (err, y) {
6070 r = r.concat(y || []);
6080 cb(err);
609 });
610 }, function (err) {
6110 callback(err, r);
612 });
613 };
6141 async.concat = doParallel(_concat);
6151 async.concatSeries = doSeries(_concat);
616
6171 async.whilst = function (test, iterator, callback) {
6180 if (test()) {
6190 iterator(function (err) {
6200 if (err) {
6210 return callback(err);
622 }
6230 async.whilst(test, iterator, callback);
624 });
625 }
626 else {
6270 callback();
628 }
629 };
630
6311 async.doWhilst = function (iterator, test, callback) {
6320 iterator(function (err) {
6330 if (err) {
6340 return callback(err);
635 }
6360 if (test()) {
6370 async.doWhilst(iterator, test, callback);
638 }
639 else {
6400 callback();
641 }
642 });
643 };
644
6451 async.until = function (test, iterator, callback) {
6460 if (!test()) {
6470 iterator(function (err) {
6480 if (err) {
6490 return callback(err);
650 }
6510 async.until(test, iterator, callback);
652 });
653 }
654 else {
6550 callback();
656 }
657 };
658
6591 async.doUntil = function (iterator, test, callback) {
6600 iterator(function (err) {
6610 if (err) {
6620 return callback(err);
663 }
6640 if (!test()) {
6650 async.doUntil(iterator, test, callback);
666 }
667 else {
6680 callback();
669 }
670 });
671 };
672
6731 async.queue = function (worker, concurrency) {
6740 if (concurrency === undefined) {
6750 concurrency = 1;
676 }
6770 function _insert(q, data, pos, callback) {
6780 if(data.constructor !== Array) {
6790 data = [data];
680 }
6810 _each(data, function(task) {
6820 var item = {
683 data: task,
684 callback: typeof callback === 'function' ? callback : null
685 };
686
6870 if (pos) {
6880 q.tasks.unshift(item);
689 } else {
6900 q.tasks.push(item);
691 }
692
6930 if (q.saturated && q.tasks.length === concurrency) {
6940 q.saturated();
695 }
6960 async.setImmediate(q.process);
697 });
698 }
699
7000 var workers = 0;
7010 var q = {
702 tasks: [],
703 concurrency: concurrency,
704 saturated: null,
705 empty: null,
706 drain: null,
707 push: function (data, callback) {
7080 _insert(q, data, false, callback);
709 },
710 unshift: function (data, callback) {
7110 _insert(q, data, true, callback);
712 },
713 process: function () {
7140 if (workers < q.concurrency && q.tasks.length) {
7150 var task = q.tasks.shift();
7160 if (q.empty && q.tasks.length === 0) {
7170 q.empty();
718 }
7190 workers += 1;
7200 var next = function () {
7210 workers -= 1;
7220 if (task.callback) {
7230 task.callback.apply(task, arguments);
724 }
7250 if (q.drain && q.tasks.length + workers === 0) {
7260 q.drain();
727 }
7280 q.process();
729 };
7300 var cb = only_once(next);
7310 worker(task.data, cb);
732 }
733 },
734 length: function () {
7350 return q.tasks.length;
736 },
737 running: function () {
7380 return workers;
739 }
740 };
7410 return q;
742 };
743
7441 async.cargo = function (worker, payload) {
7450 var working = false,
746 tasks = [];
747
7480 var cargo = {
749 tasks: tasks,
750 payload: payload,
751 saturated: null,
752 empty: null,
753 drain: null,
754 push: function (data, callback) {
7550 if(data.constructor !== Array) {
7560 data = [data];
757 }
7580 _each(data, function(task) {
7590 tasks.push({
760 data: task,
761 callback: typeof callback === 'function' ? callback : null
762 });
7630 if (cargo.saturated && tasks.length === payload) {
7640 cargo.saturated();
765 }
766 });
7670 async.setImmediate(cargo.process);
768 },
769 process: function process() {
7700 if (working) return;
7710 if (tasks.length === 0) {
7720 if(cargo.drain) cargo.drain();
7730 return;
774 }
775
7760 var ts = typeof payload === 'number'
777 ? tasks.splice(0, payload)
778 : tasks.splice(0);
779
7800 var ds = _map(ts, function (task) {
7810 return task.data;
782 });
783
7840 if(cargo.empty) cargo.empty();
7850 working = true;
7860 worker(ds, function () {
7870 working = false;
788
7890 var args = arguments;
7900 _each(ts, function (data) {
7910 if (data.callback) {
7920 data.callback.apply(null, args);
793 }
794 });
795
7960 process();
797 });
798 },
799 length: function () {
8000 return tasks.length;
801 },
802 running: function () {
8030 return working;
804 }
805 };
8060 return cargo;
807 };
808
8091 var _console_fn = function (name) {
8102 return function (fn) {
8110 var args = Array.prototype.slice.call(arguments, 1);
8120 fn.apply(null, args.concat([function (err) {
8130 var args = Array.prototype.slice.call(arguments, 1);
8140 if (typeof console !== 'undefined') {
8150 if (err) {
8160 if (console.error) {
8170 console.error(err);
818 }
819 }
8200 else if (console[name]) {
8210 _each(args, function (x) {
8220 console[name](x);
823 });
824 }
825 }
826 }]));
827 };
828 };
8291 async.log = _console_fn('log');
8301 async.dir = _console_fn('dir');
831 /*async.info = _console_fn('info');
832 async.warn = _console_fn('warn');
833 async.error = _console_fn('error');*/
834
8351 async.memoize = function (fn, hasher) {
8360 var memo = {};
8370 var queues = {};
8380 hasher = hasher || function (x) {
8390 return x;
840 };
8410 var memoized = function () {
8420 var args = Array.prototype.slice.call(arguments);
8430 var callback = args.pop();
8440 var key = hasher.apply(null, args);
8450 if (key in memo) {
8460 callback.apply(null, memo[key]);
847 }
8480 else if (key in queues) {
8490 queues[key].push(callback);
850 }
851 else {
8520 queues[key] = [callback];
8530 fn.apply(null, args.concat([function () {
8540 memo[key] = arguments;
8550 var q = queues[key];
8560 delete queues[key];
8570 for (var i = 0, l = q.length; i < l; i++) {
8580 q[i].apply(null, arguments);
859 }
860 }]));
861 }
862 };
8630 memoized.memo = memo;
8640 memoized.unmemoized = fn;
8650 return memoized;
866 };
867
8681 async.unmemoize = function (fn) {
8690 return function () {
8700 return (fn.unmemoized || fn).apply(null, arguments);
871 };
872 };
873
8741 async.times = function (count, iterator, callback) {
8750 var counter = [];
8760 for (var i = 0; i < count; i++) {
8770 counter.push(i);
878 }
8790 return async.map(counter, iterator, callback);
880 };
881
8821 async.timesSeries = function (count, iterator, callback) {
8830 var counter = [];
8840 for (var i = 0; i < count; i++) {
8850 counter.push(i);
886 }
8870 return async.mapSeries(counter, iterator, callback);
888 };
889
8901 async.compose = function (/* functions... */) {
8910 var fns = Array.prototype.reverse.call(arguments);
8920 return function () {
8930 var that = this;
8940 var args = Array.prototype.slice.call(arguments);
8950 var callback = args.pop();
8960 async.reduce(fns, args, function (newargs, fn, cb) {
8970 fn.apply(that, newargs.concat([function () {
8980 var err = arguments[0];
8990 var nextargs = Array.prototype.slice.call(arguments, 1);
9000 cb(err, nextargs);
901 }]))
902 },
903 function (err, results) {
9040 callback.apply(that, [err].concat(results));
905 });
906 };
907 };
908
9091 var _applyEach = function (eachfn, fns /*args...*/) {
9100 var go = function () {
9110 var that = this;
9120 var args = Array.prototype.slice.call(arguments);
9130 var callback = args.pop();
9140 return eachfn(fns, function (fn, cb) {
9150 fn.apply(that, args.concat([cb]));
916 },
917 callback);
918 };
9190 if (arguments.length > 2) {
9200 var args = Array.prototype.slice.call(arguments, 2);
9210 return go.apply(this, args);
922 }
923 else {
9240 return go;
925 }
926 };
9271 async.applyEach = doParallel(_applyEach);
9281 async.applyEachSeries = doSeries(_applyEach);
929
9301 async.forever = function (fn, callback) {
9310 function next(err) {
9320 if (err) {
9330 if (callback) {
9340 return callback(err);
935 }
9360 throw err;
937 }
9380 fn(next);
939 }
9400 next();
941 };
942
943 // AMD / RequireJS
9441 if (typeof define !== 'undefined' && define.amd) {
9450 define([], function () {
9460 return async;
947 });
948 }
949 // Node.js
9501 else if (typeof module !== 'undefined' && module.exports) {
9511 module.exports = async;
952 }
953 // included directly via <script> tag
954 else {
9550 root.async = async;
956 }
957
958}());
959

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/kraken-js/node_modules/shortstop/lib/resolver.js

5%
40
2
38
LineHitsSource
1/***@@@ BEGIN LICENSE @@@***/
2/*───────────────────────────────────────────────────────────────────────────*\
3│ Copyright (C) 2013 eBay Software Foundation │
4│ │
5│hh ,'""`. │
6│ / _ _ \ Licensed under the Apache License, Version 2.0 (the "License"); │
7│ |(@)(@)| you may not use this file except in compliance with the License. │
8│ ) __ ( You may obtain a copy of the License at │
9│ /,'))((`.\ │
10│(( (( )) )) http://www.apache.org/licenses/LICENSE-2.0 │
11│ `\ `)(' /' │
12│ │
13│ Unless required by applicable law or agreed to in writing, software │
14│ distributed under the License is distributed on an "AS IS" BASIS, │
15│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
16│ See the License for the specific language governing permissions and │
17│ limitations under the License. │
18\*───────────────────────────────────────────────────────────────────────────*/
19/***@@@ END LICENSE @@@***/
201'use strict';
21
22
23
241exports.create = function (parent) {
25
260 return {
27
28 _parent: parent,
29
30 _handlers: Object.create(null),
31
32 use: function (protocol, impl) {
330 var handlers, handler, index, removed;
34
350 handlers = this._handlers;
360 handler = handlers[protocol];
37
380 if(!handler) {
390 handler = handlers[protocol] = {
40
41 protocol: protocol,
42
43 regex: new RegExp('^' + protocol + ':'),
44
45 predicate: function (value) {
460 return this.regex.test(value);
47 },
48
49 stack: []
50
51 };
52 }
53
540 index = handler.stack.push(impl);
550 removed = false;
56
57 // Unuse
580 return function () {
590 if (!removed) {
600 removed = true;
610 return handler.stack.splice(index - 1, 1)[0];
62 }
630 return undefined;
64 }
65 },
66
67 getStack: function (protocol) {
680 var current, parent, hasParent;
69
700 current = this._handlers[protocol] && this._handlers[protocol].stack;
710 parent = this._parent && this._parent.getStack(protocol);
720 hasParent = parent && parent.length;
73
740 if (current && hasParent) {
750 return current.concat(parent);
76 }
77
780 if (hasParent) {
790 return parent;
80 }
81
820 return current;
83 },
84
85 resolve: function resolve(src) {
860 var dest, handlers;
87
880 dest = src;
89
900 if (typeof src === 'object' && src !== null) {
91
920 dest = (Array.isArray(src) ? [] : Object.create(Object.getPrototypeOf(src)));
930 Object.keys(src).forEach(function (key) {
940 dest[key] = this.resolve(src[key]);
95 }, this);
96
970 } else if (typeof src === 'string') {
98
990 handlers = this._handlers;
1000 Object.keys(handlers).forEach(function (protocol) {
1010 var handler = handlers[protocol];
102
1030 if (handler.predicate(src)) {
104 // run through stack and mutate
1050 dest = src.slice(protocol.length + 1);
1060 this.getStack(protocol).forEach(function (handler) {
1070 dest = handler(dest);
108 });
109 }
110 }, this);
111
112 }
113
1140 return dest;
115 }
116
117 };
118};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/browser/progress.js

21%
38
8
30
LineHitsSource
1/**
2 * Expose `Progress`.
3 */
4
51module.exports = Progress;
6
7/**
8 * Initialize a new `Progress` indicator.
9 */
10
111function Progress() {
120 this.percent = 0;
130 this.size(0);
140 this.fontSize(11);
150 this.font('helvetica, arial, sans-serif');
16}
17
18/**
19 * Set progress size to `n`.
20 *
21 * @param {Number} n
22 * @return {Progress} for chaining
23 * @api public
24 */
25
261Progress.prototype.size = function(n){
270 this._size = n;
280 return this;
29};
30
31/**
32 * Set text to `str`.
33 *
34 * @param {String} str
35 * @return {Progress} for chaining
36 * @api public
37 */
38
391Progress.prototype.text = function(str){
400 this._text = str;
410 return this;
42};
43
44/**
45 * Set font size to `n`.
46 *
47 * @param {Number} n
48 * @return {Progress} for chaining
49 * @api public
50 */
51
521Progress.prototype.fontSize = function(n){
530 this._fontSize = n;
540 return this;
55};
56
57/**
58 * Set font `family`.
59 *
60 * @param {String} family
61 * @return {Progress} for chaining
62 */
63
641Progress.prototype.font = function(family){
650 this._font = family;
660 return this;
67};
68
69/**
70 * Update percentage to `n`.
71 *
72 * @param {Number} n
73 * @return {Progress} for chaining
74 */
75
761Progress.prototype.update = function(n){
770 this.percent = n;
780 return this;
79};
80
81/**
82 * Draw on `ctx`.
83 *
84 * @param {CanvasRenderingContext2d} ctx
85 * @return {Progress} for chaining
86 */
87
881Progress.prototype.draw = function(ctx){
890 try {
900 var percent = Math.min(this.percent, 100)
91 , size = this._size
92 , half = size / 2
93 , x = half
94 , y = half
95 , rad = half - 1
96 , fontSize = this._fontSize;
97
980 ctx.font = fontSize + 'px ' + this._font;
99
1000 var angle = Math.PI * 2 * (percent / 100);
1010 ctx.clearRect(0, 0, size, size);
102
103 // outer circle
1040 ctx.strokeStyle = '#9f9f9f';
1050 ctx.beginPath();
1060 ctx.arc(x, y, rad, 0, angle, false);
1070 ctx.stroke();
108
109 // inner circle
1100 ctx.strokeStyle = '#eee';
1110 ctx.beginPath();
1120 ctx.arc(x, y, rad - 1, 0, angle, true);
1130 ctx.stroke();
114
115 // text
1160 var text = this._text || (percent | 0) + '%'
117 , w = ctx.measureText(text).width;
118
1190 ctx.fillText(
120 text
121 , x - w / 2 + 1
122 , y + fontSize / 2 - 1);
123 } catch (ex) {} //don't fail if we can't render progress
1240 return this;
125};
126

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/context.js

52%
17
9
8
LineHitsSource
1
2/**
3 * Expose `Context`.
4 */
5
61module.exports = Context;
7
8/**
9 * Initialize a new `Context`.
10 *
11 * @api private
12 */
13
141function Context(){}
15
16/**
17 * Set or get the context `Runnable` to `runnable`.
18 *
19 * @param {Runnable} runnable
20 * @return {Context}
21 * @api private
22 */
23
241Context.prototype.runnable = function(runnable){
253 if (0 == arguments.length) return this._runnable;
263 this.test = this._runnable = runnable;
273 return this;
28};
29
30/**
31 * Set test timeout `ms`.
32 *
33 * @param {Number} ms
34 * @return {Context} self
35 * @api private
36 */
37
381Context.prototype.timeout = function(ms){
390 this.runnable().timeout(ms);
400 return this;
41};
42
43/**
44 * Set test slowness threshold `ms`.
45 *
46 * @param {Number} ms
47 * @return {Context} self
48 * @api private
49 */
50
511Context.prototype.slow = function(ms){
520 this.runnable().slow(ms);
530 return this;
54};
55
56/**
57 * Inspect the context void of `._runnable`.
58 *
59 * @return {String}
60 * @api private
61 */
62
631Context.prototype.inspect = function(){
640 return JSON.stringify(this, function(key, val){
650 if ('_runnable' == key) return;
660 if ('test' == key) return;
670 return val;
68 }, 2);
69};
70

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/hook.js

91%
12
11
1
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Runnable = require('./runnable');
7
8/**
9 * Expose `Hook`.
10 */
11
121module.exports = Hook;
13
14/**
15 * Initialize a new `Hook` with the given `title` and callback `fn`.
16 *
17 * @param {String} title
18 * @param {Function} fn
19 * @api private
20 */
21
221function Hook(title, fn) {
232 Runnable.call(this, title, fn);
242 this.type = 'hook';
25}
26
27/**
28 * Inherit from `Runnable.prototype`.
29 */
30
311Hook.prototype.__proto__ = Runnable.prototype;
32
33/**
34 * Get or set the test `err`.
35 *
36 * @param {Error} err
37 * @return {Error}
38 * @api public
39 */
40
411Hook.prototype.error = function(err){
422 if (0 == arguments.length) {
432 var err = this._error;
442 this._error = null;
452 return err;
46 }
47
480 this._error = err;
49};
50

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/interfaces/bdd.js

75%
41
31
10
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Suite = require('../suite')
7 , Test = require('../test')
8 , utils = require('../utils');
9
10/**
11 * BDD-style interface:
12 *
13 * describe('Array', function(){
14 * describe('#indexOf()', function(){
15 * it('should return -1 when not present', function(){
16 *
17 * });
18 *
19 * it('should return the index when present', function(){
20 *
21 * });
22 * });
23 * });
24 *
25 */
26
271module.exports = function(suite){
282 var suites = [suite];
29
302 suite.on('pre-require', function(context, file, mocha){
31
32 /**
33 * Execute before running tests.
34 */
35
364 context.before = function(fn){
370 suites[0].beforeAll(fn);
38 };
39
40 /**
41 * Execute after running tests.
42 */
43
444 context.after = function(fn){
450 suites[0].afterAll(fn);
46 };
47
48 /**
49 * Execute before each test case.
50 */
51
524 context.beforeEach = function(fn){
533 suites[0].beforeEach(fn);
54 };
55
56 /**
57 * Execute after each test case.
58 */
59
604 context.afterEach = function(fn){
611 suites[0].afterEach(fn);
62 };
63
64 /**
65 * Describe a "suite" with the given `title`
66 * and callback `fn` containing nested suites
67 * and/or tests.
68 */
69
704 context.describe = context.context = function(title, fn){
712 var suite = Suite.create(suites[0], title);
722 suites.unshift(suite);
732 fn.call(suite);
742 suites.shift();
752 return suite;
76 };
77
78 /**
79 * Pending describe.
80 */
81
824 context.xdescribe =
83 context.xcontext =
84 context.describe.skip = function(title, fn){
851 var suite = Suite.create(suites[0], title);
861 suite.pending = true;
871 suites.unshift(suite);
881 fn.call(suite);
891 suites.shift();
90 };
91
92 /**
93 * Exclusive suite.
94 */
95
964 context.describe.only = function(title, fn){
970 var suite = context.describe(title, fn);
980 mocha.grep(suite.fullTitle());
990 return suite;
100 };
101
102 /**
103 * Describe a specification or test-case
104 * with the given `title` and callback `fn`
105 * acting as a thunk.
106 */
107
1084 context.it = context.specify = function(title, fn){
1092 var suite = suites[0];
1103 if (suite.pending) var fn = null;
1112 var test = new Test(title, fn);
1122 suite.addTest(test);
1132 return test;
114 };
115
116 /**
117 * Exclusive test-case.
118 */
119
1204 context.it.only = function(title, fn){
1210 var test = context.it(title, fn);
1220 var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
1230 mocha.grep(new RegExp(reString));
1240 return test;
125 };
126
127 /**
128 * Pending test case.
129 */
130
1314 context.xit =
132 context.xspecify =
133 context.it.skip = function(title){
1340 context.it(title);
135 };
136 });
137};
138

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/interfaces/exports.js

8%
23
2
21
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Suite = require('../suite')
7 , Test = require('../test');
8
9/**
10 * TDD-style interface:
11 *
12 * exports.Array = {
13 * '#indexOf()': {
14 * 'should return -1 when the value is not present': function(){
15 *
16 * },
17 *
18 * 'should return the correct index when the value is present': function(){
19 *
20 * }
21 * }
22 * };
23 *
24 */
25
261module.exports = function(suite){
270 var suites = [suite];
28
290 suite.on('require', visit);
30
310 function visit(obj) {
320 var suite;
330 for (var key in obj) {
340 if ('function' == typeof obj[key]) {
350 var fn = obj[key];
360 switch (key) {
37 case 'before':
380 suites[0].beforeAll(fn);
390 break;
40 case 'after':
410 suites[0].afterAll(fn);
420 break;
43 case 'beforeEach':
440 suites[0].beforeEach(fn);
450 break;
46 case 'afterEach':
470 suites[0].afterEach(fn);
480 break;
49 default:
500 suites[0].addTest(new Test(key, fn));
51 }
52 } else {
530 var suite = Suite.create(suites[0], key);
540 suites.unshift(suite);
550 visit(obj[key]);
560 suites.shift();
57 }
58 }
59 }
60};
61

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/interfaces/index.js

100%
4
4
0
LineHitsSource
1
21exports.bdd = require('./bdd');
31exports.tdd = require('./tdd');
41exports.qunit = require('./qunit');
51exports.exports = require('./exports');
6

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/interfaces/qunit.js

6%
30
2
28
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Suite = require('../suite')
7 , Test = require('../test')
8 , utils = require('../utils');
9
10/**
11 * QUnit-style interface:
12 *
13 * suite('Array');
14 *
15 * test('#length', function(){
16 * var arr = [1,2,3];
17 * ok(arr.length == 3);
18 * });
19 *
20 * test('#indexOf()', function(){
21 * var arr = [1,2,3];
22 * ok(arr.indexOf(1) == 0);
23 * ok(arr.indexOf(2) == 1);
24 * ok(arr.indexOf(3) == 2);
25 * });
26 *
27 * suite('String');
28 *
29 * test('#length', function(){
30 * ok('foo'.length == 3);
31 * });
32 *
33 */
34
351module.exports = function(suite){
360 var suites = [suite];
37
380 suite.on('pre-require', function(context, file, mocha){
39
40 /**
41 * Execute before running tests.
42 */
43
440 context.before = function(fn){
450 suites[0].beforeAll(fn);
46 };
47
48 /**
49 * Execute after running tests.
50 */
51
520 context.after = function(fn){
530 suites[0].afterAll(fn);
54 };
55
56 /**
57 * Execute before each test case.
58 */
59
600 context.beforeEach = function(fn){
610 suites[0].beforeEach(fn);
62 };
63
64 /**
65 * Execute after each test case.
66 */
67
680 context.afterEach = function(fn){
690 suites[0].afterEach(fn);
70 };
71
72 /**
73 * Describe a "suite" with the given `title`.
74 */
75
760 context.suite = function(title){
770 if (suites.length > 1) suites.shift();
780 var suite = Suite.create(suites[0], title);
790 suites.unshift(suite);
800 return suite;
81 };
82
83 /**
84 * Exclusive test-case.
85 */
86
870 context.suite.only = function(title, fn){
880 var suite = context.suite(title, fn);
890 mocha.grep(suite.fullTitle());
90 };
91
92 /**
93 * Describe a specification or test-case
94 * with the given `title` and callback `fn`
95 * acting as a thunk.
96 */
97
980 context.test = function(title, fn){
990 var test = new Test(title, fn);
1000 suites[0].addTest(test);
1010 return test;
102 };
103
104 /**
105 * Exclusive test-case.
106 */
107
1080 context.test.only = function(title, fn){
1090 var test = context.test(title, fn);
1100 var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
1110 mocha.grep(new RegExp(reString));
112 };
113
114 /**
115 * Pending test case.
116 */
117
1180 context.test.skip = function(title){
1190 context.test(title);
120 };
121 });
122};
123

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/interfaces/tdd.js

5%
39
2
37
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Suite = require('../suite')
7 , Test = require('../test')
8 , utils = require('../utils');;
9
10/**
11 * TDD-style interface:
12 *
13 * suite('Array', function(){
14 * suite('#indexOf()', function(){
15 * suiteSetup(function(){
16 *
17 * });
18 *
19 * test('should return -1 when not present', function(){
20 *
21 * });
22 *
23 * test('should return the index when present', function(){
24 *
25 * });
26 *
27 * suiteTeardown(function(){
28 *
29 * });
30 * });
31 * });
32 *
33 */
34
351module.exports = function(suite){
360 var suites = [suite];
37
380 suite.on('pre-require', function(context, file, mocha){
39
40 /**
41 * Execute before each test case.
42 */
43
440 context.setup = function(fn){
450 suites[0].beforeEach(fn);
46 };
47
48 /**
49 * Execute after each test case.
50 */
51
520 context.teardown = function(fn){
530 suites[0].afterEach(fn);
54 };
55
56 /**
57 * Execute before the suite.
58 */
59
600 context.suiteSetup = function(fn){
610 suites[0].beforeAll(fn);
62 };
63
64 /**
65 * Execute after the suite.
66 */
67
680 context.suiteTeardown = function(fn){
690 suites[0].afterAll(fn);
70 };
71
72 /**
73 * Describe a "suite" with the given `title`
74 * and callback `fn` containing nested suites
75 * and/or tests.
76 */
77
780 context.suite = function(title, fn){
790 var suite = Suite.create(suites[0], title);
800 suites.unshift(suite);
810 fn.call(suite);
820 suites.shift();
830 return suite;
84 };
85
86 /**
87 * Pending suite.
88 */
890 context.suite.skip = function(title, fn) {
900 var suite = Suite.create(suites[0], title);
910 suite.pending = true;
920 suites.unshift(suite);
930 fn.call(suite);
940 suites.shift();
95 };
96
97 /**
98 * Exclusive test-case.
99 */
100
1010 context.suite.only = function(title, fn){
1020 var suite = context.suite(title, fn);
1030 mocha.grep(suite.fullTitle());
104 };
105
106 /**
107 * Describe a specification or test-case
108 * with the given `title` and callback `fn`
109 * acting as a thunk.
110 */
111
1120 context.test = function(title, fn){
1130 var suite = suites[0];
1140 if (suite.pending) var fn = null;
1150 var test = new Test(title, fn);
1160 suite.addTest(test);
1170 return test;
118 };
119
120 /**
121 * Exclusive test-case.
122 */
123
1240 context.test.only = function(title, fn){
1250 var test = context.test(title, fn);
1260 var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
1270 mocha.grep(new RegExp(reString));
128 };
129
130 /**
131 * Pending test case.
132 */
133
1340 context.test.skip = function(title){
1350 context.test(title);
136 };
137 });
138};
139

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/mocha.js

69%
129
90
39
LineHitsSource
1/*!
2 * mocha
3 * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
4 * MIT Licensed
5 */
6
7/**
8 * Module dependencies.
9 */
10
111var path = require('path')
12 , utils = require('./utils');
13
14/**
15 * Expose `Mocha`.
16 */
17
181exports = module.exports = Mocha;
19
20/**
21 * Expose internals.
22 */
23
241exports.utils = utils;
251exports.interfaces = require('./interfaces');
261exports.reporters = require('./reporters');
271exports.Runnable = require('./runnable');
281exports.Context = require('./context');
291exports.Runner = require('./runner');
301exports.Suite = require('./suite');
311exports.Hook = require('./hook');
321exports.Test = require('./test');
33
34/**
35 * Return image `name` path.
36 *
37 * @param {String} name
38 * @return {String}
39 * @api private
40 */
41
421function image(name) {
430 return __dirname + '/../images/' + name + '.png';
44}
45
46/**
47 * Setup mocha with `options`.
48 *
49 * Options:
50 *
51 * - `ui` name "bdd", "tdd", "exports" etc
52 * - `reporter` reporter instance, defaults to `mocha.reporters.Dot`
53 * - `globals` array of accepted globals
54 * - `timeout` timeout in milliseconds
55 * - `bail` bail on the first test failure
56 * - `slow` milliseconds to wait before considering a test slow
57 * - `ignoreLeaks` ignore global leaks
58 * - `grep` string or regexp to filter tests with
59 *
60 * @param {Object} options
61 * @api public
62 */
63
641function Mocha(options) {
652 options = options || {};
662 this.files = [];
672 this.options = options;
682 this.grep(options.grep);
692 this.suite = new exports.Suite('', new exports.Context);
702 this.ui(options.ui);
712 this.bail(options.bail);
722 this.reporter(options.reporter);
733 if (null != options.timeout) this.timeout(options.timeout);
742 this.useColors(options.useColors)
752 if (options.slow) this.slow(options.slow);
76
772 this.suite.on('pre-require', function (context) {
784 exports.afterEach = context.afterEach || context.teardown;
794 exports.after = context.after || context.suiteTeardown;
804 exports.beforeEach = context.beforeEach || context.setup;
814 exports.before = context.before || context.suiteSetup;
824 exports.describe = context.describe || context.suite;
834 exports.it = context.it || context.test;
844 exports.setup = context.setup || context.beforeEach;
854 exports.suiteSetup = context.suiteSetup || context.before;
864 exports.suiteTeardown = context.suiteTeardown || context.after;
874 exports.suite = context.suite || context.describe;
884 exports.teardown = context.teardown || context.afterEach;
894 exports.test = context.test || context.it;
90 });
91}
92
93/**
94 * Enable or disable bailing on the first failure.
95 *
96 * @param {Boolean} [bail]
97 * @api public
98 */
99
1001Mocha.prototype.bail = function(bail){
1012 if (0 == arguments.length) bail = true;
1022 this.suite.bail(bail);
1032 return this;
104};
105
106/**
107 * Add test `file`.
108 *
109 * @param {String} file
110 * @api public
111 */
112
1131Mocha.prototype.addFile = function(file){
1144 this.files.push(file);
1154 return this;
116};
117
118/**
119 * Set reporter to `reporter`, defaults to "dot".
120 *
121 * @param {String|Function} reporter name or constructor
122 * @api public
123 */
124
1251Mocha.prototype.reporter = function(reporter){
1262 if ('function' == typeof reporter) {
1270 this._reporter = reporter;
128 } else {
1292 reporter = reporter || 'dot';
1302 var _reporter;
1314 try { _reporter = require('./reporters/' + reporter); } catch (err) {};
1322 if (!_reporter) try { _reporter = require(reporter); } catch (err) {};
1332 if (!_reporter && reporter === 'teamcity')
1340 console.warn('The Teamcity reporter was moved to a package named ' +
135 'mocha-teamcity-reporter ' +
136 '(https://npmjs.org/package/mocha-teamcity-reporter).');
1372 if (!_reporter) throw new Error('invalid reporter "' + reporter + '"');
1382 this._reporter = _reporter;
139 }
1402 return this;
141};
142
143/**
144 * Set test UI `name`, defaults to "bdd".
145 *
146 * @param {String} bdd
147 * @api public
148 */
149
1501Mocha.prototype.ui = function(name){
1512 name = name || 'bdd';
1522 this._ui = exports.interfaces[name];
1532 if (!this._ui) try { this._ui = require(name); } catch (err) {};
1542 if (!this._ui) throw new Error('invalid interface "' + name + '"');
1552 this._ui = this._ui(this.suite);
1562 return this;
157};
158
159/**
160 * Load registered files.
161 *
162 * @api private
163 */
164
1651Mocha.prototype.loadFiles = function(fn){
1662 var self = this;
1672 var suite = this.suite;
1682 var pending = this.files.length;
1692 this.files.forEach(function(file){
1704 file = path.resolve(file);
1714 suite.emit('pre-require', global, file, self);
1724 suite.emit('require', require(file), file, self);
1734 suite.emit('post-require', global, file, self);
1744 --pending || (fn && fn());
175 });
176};
177
178/**
179 * Enable growl support.
180 *
181 * @api private
182 */
183
1841Mocha.prototype._growl = function(runner, reporter) {
1850 var notify = require('growl');
186
1870 runner.on('end', function(){
1880 var stats = reporter.stats;
1890 if (stats.failures) {
1900 var msg = stats.failures + ' of ' + runner.total + ' tests failed';
1910 notify(msg, { name: 'mocha', title: 'Failed', image: image('error') });
192 } else {
1930 notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
194 name: 'mocha'
195 , title: 'Passed'
196 , image: image('ok')
197 });
198 }
199 });
200};
201
202/**
203 * Add regexp to grep, if `re` is a string it is escaped.
204 *
205 * @param {RegExp|String} re
206 * @return {Mocha}
207 * @api public
208 */
209
2101Mocha.prototype.grep = function(re){
2112 this.options.grep = 'string' == typeof re
212 ? new RegExp(utils.escapeRegexp(re))
213 : re;
2142 return this;
215};
216
217/**
218 * Invert `.grep()` matches.
219 *
220 * @return {Mocha}
221 * @api public
222 */
223
2241Mocha.prototype.invert = function(){
2250 this.options.invert = true;
2260 return this;
227};
228
229/**
230 * Ignore global leaks.
231 *
232 * @param {Boolean} ignore
233 * @return {Mocha}
234 * @api public
235 */
236
2371Mocha.prototype.ignoreLeaks = function(ignore){
2380 this.options.ignoreLeaks = !!ignore;
2390 return this;
240};
241
242/**
243 * Enable global leak checking.
244 *
245 * @return {Mocha}
246 * @api public
247 */
248
2491Mocha.prototype.checkLeaks = function(){
2500 this.options.ignoreLeaks = false;
2510 return this;
252};
253
254/**
255 * Enable growl support.
256 *
257 * @return {Mocha}
258 * @api public
259 */
260
2611Mocha.prototype.growl = function(){
2620 this.options.growl = true;
2630 return this;
264};
265
266/**
267 * Ignore `globals` array or string.
268 *
269 * @param {Array|String} globals
270 * @return {Mocha}
271 * @api public
272 */
273
2741Mocha.prototype.globals = function(globals){
2750 this.options.globals = (this.options.globals || []).concat(globals);
2760 return this;
277};
278
279/**
280 * Emit color output.
281 *
282 * @param {Boolean} colors
283 * @return {Mocha}
284 * @api public
285 */
286
2871Mocha.prototype.useColors = function(colors){
2882 this.options.useColors = arguments.length && colors != undefined
289 ? colors
290 : true;
2912 return this;
292};
293
294/**
295 * Use inline diffs rather than +/-.
296 *
297 * @param {Boolean} inlineDiffs
298 * @return {Mocha}
299 * @api public
300 */
301
3021Mocha.prototype.useInlineDiffs = function(inlineDiffs) {
3030 this.options.useInlineDiffs = arguments.length && inlineDiffs != undefined
304 ? inlineDiffs
305 : false;
3060 return this;
307};
308
309/**
310 * Set the timeout in milliseconds.
311 *
312 * @param {Number} timeout
313 * @return {Mocha}
314 * @api public
315 */
316
3171Mocha.prototype.timeout = function(timeout){
3181 this.suite.timeout(timeout);
3191 return this;
320};
321
322/**
323 * Set slowness threshold in milliseconds.
324 *
325 * @param {Number} slow
326 * @return {Mocha}
327 * @api public
328 */
329
3301Mocha.prototype.slow = function(slow){
3310 this.suite.slow(slow);
3320 return this;
333};
334
335/**
336 * Makes all tests async (accepting a callback)
337 *
338 * @return {Mocha}
339 * @api public
340 */
341
3421Mocha.prototype.asyncOnly = function(){
3430 this.options.asyncOnly = true;
3440 return this;
345};
346
347/**
348 * Run tests and invoke `fn()` when complete.
349 *
350 * @param {Function} fn
351 * @return {Runner}
352 * @api public
353 */
354
3551Mocha.prototype.run = function(fn){
3560 if (this.files.length) this.loadFiles();
3570 var suite = this.suite;
3580 var options = this.options;
3590 var runner = new exports.Runner(suite);
3600 var reporter = new this._reporter(runner);
3610 runner.ignoreLeaks = false !== options.ignoreLeaks;
3620 runner.asyncOnly = options.asyncOnly;
3630 if (options.grep) runner.grep(options.grep, options.invert);
3640 if (options.globals) runner.globals(options.globals);
3650 if (options.growl) this._growl(runner, reporter);
3660 exports.reporters.Base.useColors = options.useColors;
3670 exports.reporters.Base.inlineDiffs = options.useInlineDiffs;
3680 return runner.run(fn);
369};
370

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/ms.js

54%
33
18
15
LineHitsSource
1/**
2 * Helpers.
3 */
4
51var s = 1000;
61var m = s * 60;
71var h = m * 60;
81var d = h * 24;
91var y = d * 365.25;
10
11/**
12 * Parse or format the given `val`.
13 *
14 * Options:
15 *
16 * - `long` verbose formatting [false]
17 *
18 * @param {String|Number} val
19 * @param {Object} options
20 * @return {String|Number}
21 * @api public
22 */
23
241module.exports = function(val, options){
251 options = options || {};
261 if ('string' == typeof val) return parse(val);
271 return options.long ? longFormat(val) : shortFormat(val);
28};
29
30/**
31 * Parse the given `str` and return milliseconds.
32 *
33 * @param {String} str
34 * @return {Number}
35 * @api private
36 */
37
381function parse(str) {
390 var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
400 if (!match) return;
410 var n = parseFloat(match[1]);
420 var type = (match[2] || 'ms').toLowerCase();
430 switch (type) {
44 case 'years':
45 case 'year':
46 case 'y':
470 return n * y;
48 case 'days':
49 case 'day':
50 case 'd':
510 return n * d;
52 case 'hours':
53 case 'hour':
54 case 'h':
550 return n * h;
56 case 'minutes':
57 case 'minute':
58 case 'm':
590 return n * m;
60 case 'seconds':
61 case 'second':
62 case 's':
630 return n * s;
64 case 'ms':
650 return n;
66 }
67}
68
69/**
70 * Short format for `ms`.
71 *
72 * @param {Number} ms
73 * @return {String}
74 * @api private
75 */
76
771function shortFormat(ms) {
781 if (ms >= d) return Math.round(ms / d) + 'd';
791 if (ms >= h) return Math.round(ms / h) + 'h';
801 if (ms >= m) return Math.round(ms / m) + 'm';
811 if (ms >= s) return Math.round(ms / s) + 's';
821 return ms + 'ms';
83}
84
85/**
86 * Long format for `ms`.
87 *
88 * @param {Number} ms
89 * @return {String}
90 * @api private
91 */
92
931function longFormat(ms) {
940 return plural(ms, d, 'day')
95 || plural(ms, h, 'hour')
96 || plural(ms, m, 'minute')
97 || plural(ms, s, 'second')
98 || ms + ' ms';
99}
100
101/**
102 * Pluralization helper.
103 */
104
1051function plural(ms, n, name) {
1060 if (ms < n) return;
1070 if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
1080 return Math.ceil(ms / n) + ' ' + name + 's';
109}
110

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/base.js

42%
153
65
88
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var tty = require('tty')
7 , diff = require('diff')
8 , ms = require('../ms')
9 , utils = require('../utils');
10
11/**
12 * Save timer references to avoid Sinon interfering (see GH-237).
13 */
14
151var Date = global.Date
16 , setTimeout = global.setTimeout
17 , setInterval = global.setInterval
18 , clearTimeout = global.clearTimeout
19 , clearInterval = global.clearInterval;
20
21/**
22 * Check if both stdio streams are associated with a tty.
23 */
24
251var isatty = tty.isatty(1) && tty.isatty(2);
26
27/**
28 * Expose `Base`.
29 */
30
311exports = module.exports = Base;
32
33/**
34 * Enable coloring by default.
35 */
36
371exports.useColors = isatty || (process.env.MOCHA_COLORS !== undefined);
38
39/**
40 * Inline diffs instead of +/-
41 */
42
431exports.inlineDiffs = false;
44
45/**
46 * Default color map.
47 */
48
491exports.colors = {
50 'pass': 90
51 , 'fail': 31
52 , 'bright pass': 92
53 , 'bright fail': 91
54 , 'bright yellow': 93
55 , 'pending': 36
56 , 'suite': 0
57 , 'error title': 0
58 , 'error message': 31
59 , 'error stack': 90
60 , 'checkmark': 32
61 , 'fast': 90
62 , 'medium': 33
63 , 'slow': 31
64 , 'green': 32
65 , 'light': 90
66 , 'diff gutter': 90
67 , 'diff added': 42
68 , 'diff removed': 41
69};
70
71/**
72 * Default symbol map.
73 */
74
751exports.symbols = {
76 ok: '✓',
77 err: '✖',
78 dot: '․'
79};
80
81// With node.js on Windows: use symbols available in terminal default fonts
821if ('win32' == process.platform) {
830 exports.symbols.ok = '\u221A';
840 exports.symbols.err = '\u00D7';
850 exports.symbols.dot = '.';
86}
87
88/**
89 * Color `str` with the given `type`,
90 * allowing colors to be disabled,
91 * as well as user-defined color
92 * schemes.
93 *
94 * @param {String} type
95 * @param {String} str
96 * @return {String}
97 * @api private
98 */
99
1001var color = exports.color = function(type, str) {
10112 if (!exports.useColors) return str;
10212 return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
103};
104
105/**
106 * Expose term window size, with some
107 * defaults for when stderr is not a tty.
108 */
109
1101exports.window = {
111 width: isatty
112 ? process.stdout.getWindowSize
113 ? process.stdout.getWindowSize(1)[0]
114 : tty.getWindowSize()[1]
115 : 75
116};
117
118/**
119 * Expose some basic cursor interactions
120 * that are common among reporters.
121 */
122
1231exports.cursor = {
124 hide: function(){
1250 isatty && process.stdout.write('\u001b[?25l');
126 },
127
128 show: function(){
1290 isatty && process.stdout.write('\u001b[?25h');
130 },
131
132 deleteLine: function(){
1331 isatty && process.stdout.write('\u001b[2K');
134 },
135
136 beginningOfLine: function(){
1371 isatty && process.stdout.write('\u001b[0G');
138 },
139
140 CR: function(){
1411 if (isatty) {
1421 exports.cursor.deleteLine();
1431 exports.cursor.beginningOfLine();
144 } else {
1450 process.stdout.write('\r');
146 }
147 }
148};
149
150/**
151 * Outut the given `failures` as a list.
152 *
153 * @param {Array} failures
154 * @api public
155 */
156
1571exports.list = function(failures){
1580 console.error();
1590 failures.forEach(function(test, i){
160 // format
1610 var fmt = color('error title', ' %s) %s:\n')
162 + color('error message', ' %s')
163 + color('error stack', '\n%s\n');
164
165 // msg
1660 var err = test.err
167 , message = err.message || ''
168 , stack = err.stack || message
169 , index = stack.indexOf(message) + message.length
170 , msg = stack.slice(0, index)
171 , actual = err.actual
172 , expected = err.expected
173 , escape = true;
174
175 // uncaught
1760 if (err.uncaught) {
1770 msg = 'Uncaught ' + msg;
178 }
179
180 // explicitly show diff
1810 if (err.showDiff && sameType(actual, expected)) {
1820 escape = false;
1830 err.actual = actual = stringify(canonicalize(actual));
1840 err.expected = expected = stringify(canonicalize(expected));
185 }
186
187 // actual / expected diff
1880 if ('string' == typeof actual && 'string' == typeof expected) {
1890 fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
1900 var match = message.match(/^([^:]+): expected/);
1910 msg = '\n ' + color('error message', match ? match[1] : msg);
192
1930 if (exports.inlineDiffs) {
1940 msg += inlineDiff(err, escape);
195 } else {
1960 msg += unifiedDiff(err, escape);
197 }
198 }
199
200 // indent stack trace without msg
2010 stack = stack.slice(index ? index + 1 : index)
202 .replace(/^/gm, ' ');
203
2040 console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
205 });
206};
207
208/**
209 * Initialize a new `Base` reporter.
210 *
211 * All other reporters generally
212 * inherit from this reporter, providing
213 * stats such as test duration, number
214 * of tests passed / failed etc.
215 *
216 * @param {Runner} runner
217 * @api public
218 */
219
2201function Base(runner) {
2212 var self = this
222 , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }
223 , failures = this.failures = [];
224
2252 if (!runner) return;
2262 this.runner = runner;
227
2282 runner.stats = stats;
229
2302 runner.on('start', function(){
2312 stats.start = new Date;
232 });
233
2342 runner.on('suite', function(suite){
2354 stats.suites = stats.suites || 0;
2364 suite.root || stats.suites++;
237 });
238
2392 runner.on('test end', function(test){
2402 stats.tests = stats.tests || 0;
2412 stats.tests++;
242 });
243
2442 runner.on('pass', function(test){
2451 stats.passes = stats.passes || 0;
246
2471 var medium = test.slow() / 2;
2481 test.speed = test.duration > test.slow()
249 ? 'slow'
250 : test.duration > medium
251 ? 'medium'
252 : 'fast';
253
2541 stats.passes++;
255 });
256
2572 runner.on('fail', function(test, err){
2580 stats.failures = stats.failures || 0;
2590 stats.failures++;
2600 test.err = err;
2610 failures.push(test);
262 });
263
2642 runner.on('end', function(){
2652 stats.end = new Date;
2662 stats.duration = new Date - stats.start;
267 });
268
2692 runner.on('pending', function(){
2701 stats.pending++;
271 });
272}
273
274/**
275 * Output common epilogue used by many of
276 * the bundled reporters.
277 *
278 * @api public
279 */
280
2811Base.prototype.epilogue = function(){
2821 var stats = this.stats;
2831 var tests;
2841 var fmt;
285
2861 console.log();
287
288 // passes
2891 fmt = color('bright pass', ' ')
290 + color('green', ' %d passing')
291 + color('light', ' (%s)');
292
2931 console.log(fmt,
294 stats.passes || 0,
295 ms(stats.duration));
296
297 // pending
2981 if (stats.pending) {
2991 fmt = color('pending', ' ')
300 + color('pending', ' %d pending');
301
3021 console.log(fmt, stats.pending);
303 }
304
305 // failures
3061 if (stats.failures) {
3070 fmt = color('fail', ' %d failing');
308
3090 console.error(fmt,
310 stats.failures);
311
3120 Base.list(this.failures);
3130 console.error();
314 }
315
3161 console.log();
317};
318
319/**
320 * Pad the given `str` to `len`.
321 *
322 * @param {String} str
323 * @param {String} len
324 * @return {String}
325 * @api private
326 */
327
3281function pad(str, len) {
3290 str = String(str);
3300 return Array(len - str.length + 1).join(' ') + str;
331}
332
333
334/**
335 * Returns an inline diff between 2 strings with coloured ANSI output
336 *
337 * @param {Error} Error with actual/expected
338 * @return {String} Diff
339 * @api private
340 */
341
3421function inlineDiff(err, escape) {
3430 var msg = errorDiff(err, 'WordsWithSpace', escape);
344
345 // linenos
3460 var lines = msg.split('\n');
3470 if (lines.length > 4) {
3480 var width = String(lines.length).length;
3490 msg = lines.map(function(str, i){
3500 return pad(++i, width) + ' |' + ' ' + str;
351 }).join('\n');
352 }
353
354 // legend
3550 msg = '\n'
356 + color('diff removed', 'actual')
357 + ' '
358 + color('diff added', 'expected')
359 + '\n\n'
360 + msg
361 + '\n';
362
363 // indent
3640 msg = msg.replace(/^/gm, ' ');
3650 return msg;
366}
367
368/**
369 * Returns a unified diff between 2 strings
370 *
371 * @param {Error} Error with actual/expected
372 * @return {String} Diff
373 * @api private
374 */
375
3761function unifiedDiff(err, escape) {
3770 var indent = ' ';
3780 function cleanUp(line) {
3790 if (escape) {
3800 line = escapeInvisibles(line);
381 }
3820 if (line[0] === '+') return indent + colorLines('diff added', line);
3830 if (line[0] === '-') return indent + colorLines('diff removed', line);
3840 if (line.match(/\@\@/)) return null;
3850 if (line.match(/\\ No newline/)) return null;
3860 else return indent + line;
387 }
3880 function notBlank(line) {
3890 return line != null;
390 }
3910 msg = diff.createPatch('string', err.actual, err.expected);
3920 var lines = msg.split('\n').splice(4);
3930 return '\n '
394 + colorLines('diff added', '+ expected') + ' '
395 + colorLines('diff removed', '- actual')
396 + '\n\n'
397 + lines.map(cleanUp).filter(notBlank).join('\n');
398}
399
400/**
401 * Return a character diff for `err`.
402 *
403 * @param {Error} err
404 * @return {String}
405 * @api private
406 */
407
4081function errorDiff(err, type, escape) {
4090 var actual = escape ? escapeInvisibles(err.actual) : err.actual;
4100 var expected = escape ? escapeInvisibles(err.expected) : err.expected;
4110 return diff['diff' + type](actual, expected).map(function(str){
4120 if (str.added) return colorLines('diff added', str.value);
4130 if (str.removed) return colorLines('diff removed', str.value);
4140 return str.value;
415 }).join('');
416}
417
418/**
419 * Returns a string with all invisible characters in plain text
420 *
421 * @param {String} line
422 * @return {String}
423 * @api private
424 */
4251function escapeInvisibles(line) {
4260 return line.replace(/\t/g, '<tab>')
427 .replace(/\r/g, '<CR>')
428 .replace(/\n/g, '<LF>\n');
429}
430
431/**
432 * Color lines for `str`, using the color `name`.
433 *
434 * @param {String} name
435 * @param {String} str
436 * @return {String}
437 * @api private
438 */
439
4401function colorLines(name, str) {
4410 return str.split('\n').map(function(str){
4420 return color(name, str);
443 }).join('\n');
444}
445
446/**
447 * Stringify `obj`.
448 *
449 * @param {Object} obj
450 * @return {String}
451 * @api private
452 */
453
4541function stringify(obj) {
4550 if (obj instanceof RegExp) return obj.toString();
4560 return JSON.stringify(obj, null, 2);
457}
458
459/**
460 * Return a new object that has the keys in sorted order.
461 * @param {Object} obj
462 * @return {Object}
463 * @api private
464 */
465
4661 function canonicalize(obj, stack) {
4670 stack = stack || [];
468
4690 if (utils.indexOf(stack, obj) !== -1) return obj;
470
4710 var canonicalizedObj;
472
4730 if ('[object Array]' == {}.toString.call(obj)) {
4740 stack.push(obj);
4750 canonicalizedObj = utils.map(obj, function(item) {
4760 return canonicalize(item, stack);
477 });
4780 stack.pop();
4790 } else if (typeof obj === 'object' && obj !== null) {
4800 stack.push(obj);
4810 canonicalizedObj = {};
4820 utils.forEach(utils.keys(obj).sort(), function(key) {
4830 canonicalizedObj[key] = canonicalize(obj[key], stack);
484 });
4850 stack.pop();
486 } else {
4870 canonicalizedObj = obj;
488 }
489
4900 return canonicalizedObj;
491 }
492
493/**
494 * Check that a / b have the same type.
495 *
496 * @param {Object} a
497 * @param {Object} b
498 * @return {Boolean}
499 * @api private
500 */
501
5021function sameType(a, b) {
5030 a = Object.prototype.toString.call(a);
5040 b = Object.prototype.toString.call(b);
5050 return a == b;
506}
507
508

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/doc.js

12%
24
3
21
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , utils = require('../utils');
8
9/**
10 * Expose `Doc`.
11 */
12
131exports = module.exports = Doc;
14
15/**
16 * Initialize a new `Doc` reporter.
17 *
18 * @param {Runner} runner
19 * @api public
20 */
21
221function Doc(runner) {
230 Base.call(this, runner);
24
250 var self = this
26 , stats = this.stats
27 , total = runner.total
28 , indents = 2;
29
300 function indent() {
310 return Array(indents).join(' ');
32 }
33
340 runner.on('suite', function(suite){
350 if (suite.root) return;
360 ++indents;
370 console.log('%s<section class="suite">', indent());
380 ++indents;
390 console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title));
400 console.log('%s<dl>', indent());
41 });
42
430 runner.on('suite end', function(suite){
440 if (suite.root) return;
450 console.log('%s</dl>', indent());
460 --indents;
470 console.log('%s</section>', indent());
480 --indents;
49 });
50
510 runner.on('pass', function(test){
520 console.log('%s <dt>%s</dt>', indent(), utils.escape(test.title));
530 var code = utils.escape(utils.clean(test.fn.toString()));
540 console.log('%s <dd><pre><code>%s</code></pre></dd>', indent(), code);
55 });
56}
57

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/dot.js

19%
21
4
17
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , color = Base.color;
8
9/**
10 * Expose `Dot`.
11 */
12
131exports = module.exports = Dot;
14
15/**
16 * Initialize a new `Dot` matrix test reporter.
17 *
18 * @param {Runner} runner
19 * @api public
20 */
21
221function Dot(runner) {
230 Base.call(this, runner);
24
250 var self = this
26 , stats = this.stats
27 , width = Base.window.width * .75 | 0
28 , n = 0;
29
300 runner.on('start', function(){
310 process.stdout.write('\n ');
32 });
33
340 runner.on('pending', function(test){
350 process.stdout.write(color('pending', Base.symbols.dot));
36 });
37
380 runner.on('pass', function(test){
390 if (++n % width == 0) process.stdout.write('\n ');
400 if ('slow' == test.speed) {
410 process.stdout.write(color('bright yellow', Base.symbols.dot));
42 } else {
430 process.stdout.write(color(test.speed, Base.symbols.dot));
44 }
45 });
46
470 runner.on('fail', function(test, err){
480 if (++n % width == 0) process.stdout.write('\n ');
490 process.stdout.write(color('fail', Base.symbols.dot));
50 });
51
520 runner.on('end', function(){
530 console.log();
540 self.epilogue();
55 });
56}
57
58/**
59 * Inherit from `Base.prototype`.
60 */
61
621Dot.prototype.__proto__ = Base.prototype;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/html-cov.js

58%
12
7
5
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var JSONCov = require('./json-cov')
7 , fs = require('fs');
8
9/**
10 * Expose `HTMLCov`.
11 */
12
131exports = module.exports = HTMLCov;
14
15/**
16 * Initialize a new `JsCoverage` reporter.
17 *
18 * @param {Runner} runner
19 * @api public
20 */
21
221function HTMLCov(runner) {
231 var jade = require('jade')
24 , file = __dirname + '/templates/coverage.jade'
25 , str = fs.readFileSync(file, 'utf8')
26 , fn = jade.compile(str, { filename: file })
27 , self = this;
28
291 JSONCov.call(this, runner, false);
30
311 runner.on('end', function(){
320 process.stdout.write(fn({
33 cov: self.cov
34 , coverageClass: coverageClass
35 }));
36 });
37}
38
39/**
40 * Return coverage class for `n`.
41 *
42 * @return {String}
43 * @api private
44 */
45
461function coverageClass(n) {
470 if (n >= 75) return 'high';
480 if (n >= 50) return 'medium';
490 if (n >= 25) return 'low';
500 return 'terrible';
51}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/html.js

12%
101
13
88
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , utils = require('../utils')
8 , Progress = require('../browser/progress')
9 , escape = utils.escape;
10
11/**
12 * Save timer references to avoid Sinon interfering (see GH-237).
13 */
14
151var Date = global.Date
16 , setTimeout = global.setTimeout
17 , setInterval = global.setInterval
18 , clearTimeout = global.clearTimeout
19 , clearInterval = global.clearInterval;
20
21/**
22 * Expose `HTML`.
23 */
24
251exports = module.exports = HTML;
26
27/**
28 * Stats template.
29 */
30
311var statsTemplate = '<ul id="mocha-stats">'
32 + '<li class="progress"><canvas width="40" height="40"></canvas></li>'
33 + '<li class="passes"><a href="#">passes:</a> <em>0</em></li>'
34 + '<li class="failures"><a href="#">failures:</a> <em>0</em></li>'
35 + '<li class="duration">duration: <em>0</em>s</li>'
36 + '</ul>';
37
38/**
39 * Initialize a new `HTML` reporter.
40 *
41 * @param {Runner} runner
42 * @api public
43 */
44
451function HTML(runner, root) {
460 Base.call(this, runner);
47
480 var self = this
49 , stats = this.stats
50 , total = runner.total
51 , stat = fragment(statsTemplate)
52 , items = stat.getElementsByTagName('li')
53 , passes = items[1].getElementsByTagName('em')[0]
54 , passesLink = items[1].getElementsByTagName('a')[0]
55 , failures = items[2].getElementsByTagName('em')[0]
56 , failuresLink = items[2].getElementsByTagName('a')[0]
57 , duration = items[3].getElementsByTagName('em')[0]
58 , canvas = stat.getElementsByTagName('canvas')[0]
59 , report = fragment('<ul id="mocha-report"></ul>')
60 , stack = [report]
61 , progress
62 , ctx
63
640 root = root || document.getElementById('mocha');
65
660 if (canvas.getContext) {
670 var ratio = window.devicePixelRatio || 1;
680 canvas.style.width = canvas.width;
690 canvas.style.height = canvas.height;
700 canvas.width *= ratio;
710 canvas.height *= ratio;
720 ctx = canvas.getContext('2d');
730 ctx.scale(ratio, ratio);
740 progress = new Progress;
75 }
76
770 if (!root) return error('#mocha div missing, add it to your document');
78
79 // pass toggle
800 on(passesLink, 'click', function(){
810 unhide();
820 var name = /pass/.test(report.className) ? '' : ' pass';
830 report.className = report.className.replace(/fail|pass/g, '') + name;
840 if (report.className.trim()) hideSuitesWithout('test pass');
85 });
86
87 // failure toggle
880 on(failuresLink, 'click', function(){
890 unhide();
900 var name = /fail/.test(report.className) ? '' : ' fail';
910 report.className = report.className.replace(/fail|pass/g, '') + name;
920 if (report.className.trim()) hideSuitesWithout('test fail');
93 });
94
950 root.appendChild(stat);
960 root.appendChild(report);
97
980 if (progress) progress.size(40);
99
1000 runner.on('suite', function(suite){
1010 if (suite.root) return;
102
103 // suite
1040 var url = self.suiteURL(suite);
1050 var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, escape(suite.title));
106
107 // container
1080 stack[0].appendChild(el);
1090 stack.unshift(document.createElement('ul'));
1100 el.appendChild(stack[0]);
111 });
112
1130 runner.on('suite end', function(suite){
1140 if (suite.root) return;
1150 stack.shift();
116 });
117
1180 runner.on('fail', function(test, err){
1190 if ('hook' == test.type) runner.emit('test end', test);
120 });
121
1220 runner.on('test end', function(test){
123 // TODO: add to stats
1240 var percent = stats.tests / this.total * 100 | 0;
1250 if (progress) progress.update(percent).draw(ctx);
126
127 // update stats
1280 var ms = new Date - stats.start;
1290 text(passes, stats.passes);
1300 text(failures, stats.failures);
1310 text(duration, (ms / 1000).toFixed(2));
132
133 // test
1340 if ('passed' == test.state) {
1350 var url = self.testURL(test);
1360 var el = fragment('<li class="test pass %e"><h2>%e<span class="duration">%ems</span> <a href="%s" class="replay">‣</a></h2></li>', test.speed, test.title, test.duration, url);
1370 } else if (test.pending) {
1380 var el = fragment('<li class="test pass pending"><h2>%e</h2></li>', test.title);
139 } else {
1400 var el = fragment('<li class="test fail"><h2>%e <a href="?grep=%e" class="replay">‣</a></h2></li>', test.title, encodeURIComponent(test.fullTitle()));
1410 var str = test.err.stack || test.err.toString();
142
143 // FF / Opera do not add the message
1440 if (!~str.indexOf(test.err.message)) {
1450 str = test.err.message + '\n' + str;
146 }
147
148 // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
149 // check for the result of the stringifying.
1500 if ('[object Error]' == str) str = test.err.message;
151
152 // Safari doesn't give you a stack. Let's at least provide a source line.
1530 if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
1540 str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
155 }
156
1570 el.appendChild(fragment('<pre class="error">%e</pre>', str));
158 }
159
160 // toggle code
161 // TODO: defer
1620 if (!test.pending) {
1630 var h2 = el.getElementsByTagName('h2')[0];
164
1650 on(h2, 'click', function(){
1660 pre.style.display = 'none' == pre.style.display
167 ? 'block'
168 : 'none';
169 });
170
1710 var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString()));
1720 el.appendChild(pre);
1730 pre.style.display = 'none';
174 }
175
176 // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.
1770 if (stack[0]) stack[0].appendChild(el);
178 });
179}
180
181/**
182 * Provide suite URL
183 *
184 * @param {Object} [suite]
185 */
186
1871HTML.prototype.suiteURL = function(suite){
1880 return '?grep=' + encodeURIComponent(suite.fullTitle());
189};
190
191/**
192 * Provide test URL
193 *
194 * @param {Object} [test]
195 */
196
1971HTML.prototype.testURL = function(test){
1980 return '?grep=' + encodeURIComponent(test.fullTitle());
199};
200
201/**
202 * Display error `msg`.
203 */
204
2051function error(msg) {
2060 document.body.appendChild(fragment('<div id="mocha-error">%s</div>', msg));
207}
208
209/**
210 * Return a DOM fragment from `html`.
211 */
212
2131function fragment(html) {
2140 var args = arguments
215 , div = document.createElement('div')
216 , i = 1;
217
2180 div.innerHTML = html.replace(/%([se])/g, function(_, type){
2190 switch (type) {
2200 case 's': return String(args[i++]);
2210 case 'e': return escape(args[i++]);
222 }
223 });
224
2250 return div.firstChild;
226}
227
228/**
229 * Check for suites that do not have elements
230 * with `classname`, and hide them.
231 */
232
2331function hideSuitesWithout(classname) {
2340 var suites = document.getElementsByClassName('suite');
2350 for (var i = 0; i < suites.length; i++) {
2360 var els = suites[i].getElementsByClassName(classname);
2370 if (0 == els.length) suites[i].className += ' hidden';
238 }
239}
240
241/**
242 * Unhide .hidden suites.
243 */
244
2451function unhide() {
2460 var els = document.getElementsByClassName('suite hidden');
2470 for (var i = 0; i < els.length; ++i) {
2480 els[i].className = els[i].className.replace('suite hidden', 'suite');
249 }
250}
251
252/**
253 * Set `el` text to `str`.
254 */
255
2561function text(el, str) {
2570 if (el.textContent) {
2580 el.textContent = str;
259 } else {
2600 el.innerText = str;
261 }
262}
263
264/**
265 * Listen on `event` with callback `fn`.
266 */
267
2681function on(el, event, fn) {
2690 if (el.addEventListener) {
2700 el.addEventListener(event, fn, false);
271 } else {
2720 el.attachEvent('on' + event, fn);
273 }
274}
275

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/index.js

100%
17
17
0
LineHitsSource
1
21exports.Base = require('./base');
31exports.Dot = require('./dot');
41exports.Doc = require('./doc');
51exports.TAP = require('./tap');
61exports.JSON = require('./json');
71exports.HTML = require('./html');
81exports.List = require('./list');
91exports.Min = require('./min');
101exports.Spec = require('./spec');
111exports.Nyan = require('./nyan');
121exports.XUnit = require('./xunit');
131exports.Markdown = require('./markdown');
141exports.Progress = require('./progress');
151exports.Landing = require('./landing');
161exports.JSONCov = require('./json-cov');
171exports.HTMLCov = require('./html-cov');
181exports.JSONStream = require('./json-stream');
19

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/json-cov.js

69%
49
34
15
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base');
7
8/**
9 * Expose `JSONCov`.
10 */
11
121exports = module.exports = JSONCov;
13
14/**
15 * Initialize a new `JsCoverage` reporter.
16 *
17 * @param {Runner} runner
18 * @param {Boolean} output
19 * @api public
20 */
21
221function JSONCov(runner, output) {
231 var self = this
24 , output = 1 == arguments.length ? true : output;
25
261 Base.call(this, runner);
27
281 var tests = []
29 , failures = []
30 , passes = [];
31
321 runner.on('test end', function(test){
330 tests.push(test);
34 });
35
361 runner.on('pass', function(test){
370 passes.push(test);
38 });
39
401 runner.on('fail', function(test){
410 failures.push(test);
42 });
43
441 runner.on('end', function(){
451 var cov = global._$jscoverage || {};
461 var result = self.cov = map(cov);
470 result.stats = self.stats;
480 result.tests = tests.map(clean);
490 result.failures = failures.map(clean);
500 result.passes = passes.map(clean);
510 if (!output) return;
520 process.stdout.write(JSON.stringify(result, null, 2 ));
53 });
54}
55
56/**
57 * Map jscoverage data to a JSON structure
58 * suitable for reporting.
59 *
60 * @param {Object} cov
61 * @return {Object}
62 * @api private
63 */
64
651function map(cov) {
661 var ret = {
67 instrumentation: 'node-jscoverage'
68 , sloc: 0
69 , hits: 0
70 , misses: 0
71 , coverage: 0
72 , files: []
73 };
74
751 for (var filename in cov) {
7630 var data = coverage(filename, cov[filename]);
7729 ret.files.push(data);
7829 ret.hits += data.hits;
7929 ret.misses += data.misses;
8029 ret.sloc += data.sloc;
81 }
82
830 ret.files.sort(function(a, b) {
840 return a.filename.localeCompare(b.filename);
85 });
86
870 if (ret.sloc > 0) {
880 ret.coverage = (ret.hits / ret.sloc) * 100;
89 }
90
910 return ret;
92};
93
94/**
95 * Map jscoverage data for a single source file
96 * to a JSON structure suitable for reporting.
97 *
98 * @param {String} filename name of the source file
99 * @param {Object} data jscoverage coverage data
100 * @return {Object}
101 * @api private
102 */
103
1041function coverage(filename, data) {
10530 var ret = {
106 filename: filename,
107 coverage: 0,
108 hits: 0,
109 misses: 0,
110 sloc: 0,
111 source: {}
112 };
113
11430 data.source.forEach(function(line, num){
1154153 num++;
116
1174155 if (data[num] === 0) {
118796 ret.misses++;
119796 ret.sloc++;
1203362 } else if (data[num] !== undefined) {
121587 ret.hits++;
122588 ret.sloc++;
123 }
124
1254163 ret.source[num] = {
126 source: line
127 , coverage: data[num] === undefined
128 ? ''
129 : data[num]
130 };
131 });
132
13329 ret.coverage = ret.hits / ret.sloc * 100;
134
13529 return ret;
136}
137
138/**
139 * Return a plain-object representation of `test`
140 * free of cyclic properties etc.
141 *
142 * @param {Object} test
143 * @return {Object}
144 * @api private
145 */
146
1471function clean(test) {
1480 return {
149 title: test.title
150 , fullTitle: test.fullTitle()
151 , duration: test.duration
152 }
153}
154

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/json-stream.js

26%
15
4
11
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , color = Base.color;
8
9/**
10 * Expose `List`.
11 */
12
131exports = module.exports = List;
14
15/**
16 * Initialize a new `List` test reporter.
17 *
18 * @param {Runner} runner
19 * @api public
20 */
21
221function List(runner) {
230 Base.call(this, runner);
24
250 var self = this
26 , stats = this.stats
27 , total = runner.total;
28
290 runner.on('start', function(){
300 console.log(JSON.stringify(['start', { total: total }]));
31 });
32
330 runner.on('pass', function(test){
340 console.log(JSON.stringify(['pass', clean(test)]));
35 });
36
370 runner.on('fail', function(test, err){
380 console.log(JSON.stringify(['fail', clean(test)]));
39 });
40
410 runner.on('end', function(){
420 process.stdout.write(JSON.stringify(['end', self.stats]));
43 });
44}
45
46/**
47 * Return a plain-object representation of `test`
48 * free of cyclic properties etc.
49 *
50 * @param {Object} test
51 * @return {Object}
52 * @api private
53 */
54
551function clean(test) {
560 return {
57 title: test.title
58 , fullTitle: test.fullTitle()
59 , duration: test.duration
60 }
61}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/json.js

23%
17
4
13
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , cursor = Base.cursor
8 , color = Base.color;
9
10/**
11 * Expose `JSON`.
12 */
13
141exports = module.exports = JSONReporter;
15
16/**
17 * Initialize a new `JSON` reporter.
18 *
19 * @param {Runner} runner
20 * @api public
21 */
22
231function JSONReporter(runner) {
240 var self = this;
250 Base.call(this, runner);
26
270 var tests = []
28 , failures = []
29 , passes = [];
30
310 runner.on('test end', function(test){
320 tests.push(test);
33 });
34
350 runner.on('pass', function(test){
360 passes.push(test);
37 });
38
390 runner.on('fail', function(test){
400 failures.push(test);
41 });
42
430 runner.on('end', function(){
440 var obj = {
45 stats: self.stats
46 , tests: tests.map(clean)
47 , failures: failures.map(clean)
48 , passes: passes.map(clean)
49 };
50
510 process.stdout.write(JSON.stringify(obj, null, 2));
52 });
53}
54
55/**
56 * Return a plain-object representation of `test`
57 * free of cyclic properties etc.
58 *
59 * @param {Object} test
60 * @return {Object}
61 * @api private
62 */
63
641function clean(test) {
650 return {
66 title: test.title
67 , fullTitle: test.fullTitle()
68 , duration: test.duration
69 }
70}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/landing.js

21%
32
7
25
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , cursor = Base.cursor
8 , color = Base.color;
9
10/**
11 * Expose `Landing`.
12 */
13
141exports = module.exports = Landing;
15
16/**
17 * Airplane color.
18 */
19
201Base.colors.plane = 0;
21
22/**
23 * Airplane crash color.
24 */
25
261Base.colors['plane crash'] = 31;
27
28/**
29 * Runway color.
30 */
31
321Base.colors.runway = 90;
33
34/**
35 * Initialize a new `Landing` reporter.
36 *
37 * @param {Runner} runner
38 * @api public
39 */
40
411function Landing(runner) {
420 Base.call(this, runner);
43
440 var self = this
45 , stats = this.stats
46 , width = Base.window.width * .75 | 0
47 , total = runner.total
48 , stream = process.stdout
49 , plane = color('plane', '✈')
50 , crashed = -1
51 , n = 0;
52
530 function runway() {
540 var buf = Array(width).join('-');
550 return ' ' + color('runway', buf);
56 }
57
580 runner.on('start', function(){
590 stream.write('\n ');
600 cursor.hide();
61 });
62
630 runner.on('test end', function(test){
64 // check if the plane crashed
650 var col = -1 == crashed
66 ? width * ++n / total | 0
67 : crashed;
68
69 // show the crash
700 if ('failed' == test.state) {
710 plane = color('plane crash', '✈');
720 crashed = col;
73 }
74
75 // render landing strip
760 stream.write('\u001b[4F\n\n');
770 stream.write(runway());
780 stream.write('\n ');
790 stream.write(color('runway', Array(col).join('â‹…')));
800 stream.write(plane)
810 stream.write(color('runway', Array(width - col).join('â‹…') + '\n'));
820 stream.write(runway());
830 stream.write('\u001b[0m');
84 });
85
860 runner.on('end', function(){
870 cursor.show();
880 console.log();
890 self.epilogue();
90 });
91}
92
93/**
94 * Inherit from `Base.prototype`.
95 */
96
971Landing.prototype.__proto__ = Base.prototype;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/list.js

19%
21
4
17
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , cursor = Base.cursor
8 , color = Base.color;
9
10/**
11 * Expose `List`.
12 */
13
141exports = module.exports = List;
15
16/**
17 * Initialize a new `List` test reporter.
18 *
19 * @param {Runner} runner
20 * @api public
21 */
22
231function List(runner) {
240 Base.call(this, runner);
25
260 var self = this
27 , stats = this.stats
28 , n = 0;
29
300 runner.on('start', function(){
310 console.log();
32 });
33
340 runner.on('test', function(test){
350 process.stdout.write(color('pass', ' ' + test.fullTitle() + ': '));
36 });
37
380 runner.on('pending', function(test){
390 var fmt = color('checkmark', ' -')
40 + color('pending', ' %s');
410 console.log(fmt, test.fullTitle());
42 });
43
440 runner.on('pass', function(test){
450 var fmt = color('checkmark', ' '+Base.symbols.dot)
46 + color('pass', ' %s: ')
47 + color(test.speed, '%dms');
480 cursor.CR();
490 console.log(fmt, test.fullTitle(), test.duration);
50 });
51
520 runner.on('fail', function(test, err){
530 cursor.CR();
540 console.log(color('fail', ' %d) %s'), ++n, test.fullTitle());
55 });
56
570 runner.on('end', self.epilogue.bind(self));
58}
59
60/**
61 * Inherit from `Base.prototype`.
62 */
63
641List.prototype.__proto__ = Base.prototype;
65

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/markdown.js

6%
47
3
44
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var Base = require('./base')
6 , utils = require('../utils');
7
8/**
9 * Expose `Markdown`.
10 */
11
121exports = module.exports = Markdown;
13
14/**
15 * Initialize a new `Markdown` reporter.
16 *
17 * @param {Runner} runner
18 * @api public
19 */
20
211function Markdown(runner) {
220 Base.call(this, runner);
23
240 var self = this
25 , stats = this.stats
26 , level = 0
27 , buf = '';
28
290 function title(str) {
300 return Array(level).join('#') + ' ' + str;
31 }
32
330 function indent() {
340 return Array(level).join(' ');
35 }
36
370 function mapTOC(suite, obj) {
380 var ret = obj;
390 obj = obj[suite.title] = obj[suite.title] || { suite: suite };
400 suite.suites.forEach(function(suite){
410 mapTOC(suite, obj);
42 });
430 return ret;
44 }
45
460 function stringifyTOC(obj, level) {
470 ++level;
480 var buf = '';
490 var link;
500 for (var key in obj) {
510 if ('suite' == key) continue;
520 if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
530 if (key) buf += Array(level).join(' ') + link;
540 buf += stringifyTOC(obj[key], level);
55 }
560 --level;
570 return buf;
58 }
59
600 function generateTOC(suite) {
610 var obj = mapTOC(suite, {});
620 return stringifyTOC(obj, 0);
63 }
64
650 generateTOC(runner.suite);
66
670 runner.on('suite', function(suite){
680 ++level;
690 var slug = utils.slug(suite.fullTitle());
700 buf += '<a name="' + slug + '"></a>' + '\n';
710 buf += title(suite.title) + '\n';
72 });
73
740 runner.on('suite end', function(suite){
750 --level;
76 });
77
780 runner.on('pass', function(test){
790 var code = utils.clean(test.fn.toString());
800 buf += test.title + '.\n';
810 buf += '\n```js\n';
820 buf += code + '\n';
830 buf += '```\n\n';
84 });
85
860 runner.on('end', function(){
870 process.stdout.write('# TOC\n');
880 process.stdout.write(generateTOC(runner.suite));
890 process.stdout.write(buf);
90 });
91}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/min.js

44%
9
4
5
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base');
7
8/**
9 * Expose `Min`.
10 */
11
121exports = module.exports = Min;
13
14/**
15 * Initialize a new `Min` minimal test reporter (best used with --watch).
16 *
17 * @param {Runner} runner
18 * @api public
19 */
20
211function Min(runner) {
220 Base.call(this, runner);
23
240 runner.on('start', function(){
25 // clear screen
260 process.stdout.write('\u001b[2J');
27 // set cursor position
280 process.stdout.write('\u001b[1;3H');
29 });
30
310 runner.on('end', this.epilogue.bind(this));
32}
33
34/**
35 * Inherit from `Base.prototype`.
36 */
37
381Min.prototype.__proto__ = Base.prototype;
39

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/nyan.js

14%
103
15
88
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var Base = require('./base')
6 , color = Base.color;
7
8/**
9 * Expose `Dot`.
10 */
11
121exports = module.exports = NyanCat;
13
14/**
15 * Initialize a new `Dot` matrix test reporter.
16 *
17 * @param {Runner} runner
18 * @api public
19 */
20
211function NyanCat(runner) {
220 Base.call(this, runner);
230 var self = this
24 , stats = this.stats
25 , width = Base.window.width * .75 | 0
26 , rainbowColors = this.rainbowColors = self.generateColors()
27 , colorIndex = this.colorIndex = 0
28 , numerOfLines = this.numberOfLines = 4
29 , trajectories = this.trajectories = [[], [], [], []]
30 , nyanCatWidth = this.nyanCatWidth = 11
31 , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth)
32 , scoreboardWidth = this.scoreboardWidth = 5
33 , tick = this.tick = 0
34 , n = 0;
35
360 runner.on('start', function(){
370 Base.cursor.hide();
380 self.draw();
39 });
40
410 runner.on('pending', function(test){
420 self.draw();
43 });
44
450 runner.on('pass', function(test){
460 self.draw();
47 });
48
490 runner.on('fail', function(test, err){
500 self.draw();
51 });
52
530 runner.on('end', function(){
540 Base.cursor.show();
550 for (var i = 0; i < self.numberOfLines; i++) write('\n');
560 self.epilogue();
57 });
58}
59
60/**
61 * Draw the nyan cat
62 *
63 * @api private
64 */
65
661NyanCat.prototype.draw = function(){
670 this.appendRainbow();
680 this.drawScoreboard();
690 this.drawRainbow();
700 this.drawNyanCat();
710 this.tick = !this.tick;
72};
73
74/**
75 * Draw the "scoreboard" showing the number
76 * of passes, failures and pending tests.
77 *
78 * @api private
79 */
80
811NyanCat.prototype.drawScoreboard = function(){
820 var stats = this.stats;
830 var colors = Base.colors;
84
850 function draw(color, n) {
860 write(' ');
870 write('\u001b[' + color + 'm' + n + '\u001b[0m');
880 write('\n');
89 }
90
910 draw(colors.green, stats.passes);
920 draw(colors.fail, stats.failures);
930 draw(colors.pending, stats.pending);
940 write('\n');
95
960 this.cursorUp(this.numberOfLines);
97};
98
99/**
100 * Append the rainbow.
101 *
102 * @api private
103 */
104
1051NyanCat.prototype.appendRainbow = function(){
1060 var segment = this.tick ? '_' : '-';
1070 var rainbowified = this.rainbowify(segment);
108
1090 for (var index = 0; index < this.numberOfLines; index++) {
1100 var trajectory = this.trajectories[index];
1110 if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift();
1120 trajectory.push(rainbowified);
113 }
114};
115
116/**
117 * Draw the rainbow.
118 *
119 * @api private
120 */
121
1221NyanCat.prototype.drawRainbow = function(){
1230 var self = this;
124
1250 this.trajectories.forEach(function(line, index) {
1260 write('\u001b[' + self.scoreboardWidth + 'C');
1270 write(line.join(''));
1280 write('\n');
129 });
130
1310 this.cursorUp(this.numberOfLines);
132};
133
134/**
135 * Draw the nyan cat
136 *
137 * @api private
138 */
139
1401NyanCat.prototype.drawNyanCat = function() {
1410 var self = this;
1420 var startWidth = this.scoreboardWidth + this.trajectories[0].length;
1430 var color = '\u001b[' + startWidth + 'C';
1440 var padding = '';
145
1460 write(color);
1470 write('_,------,');
1480 write('\n');
149
1500 write(color);
1510 padding = self.tick ? ' ' : ' ';
1520 write('_|' + padding + '/\\_/\\ ');
1530 write('\n');
154
1550 write(color);
1560 padding = self.tick ? '_' : '__';
1570 var tail = self.tick ? '~' : '^';
1580 var face;
1590 write(tail + '|' + padding + this.face() + ' ');
1600 write('\n');
161
1620 write(color);
1630 padding = self.tick ? ' ' : ' ';
1640 write(padding + '"" "" ');
1650 write('\n');
166
1670 this.cursorUp(this.numberOfLines);
168};
169
170/**
171 * Draw nyan cat face.
172 *
173 * @return {String}
174 * @api private
175 */
176
1771NyanCat.prototype.face = function() {
1780 var stats = this.stats;
1790 if (stats.failures) {
1800 return '( x .x)';
1810 } else if (stats.pending) {
1820 return '( o .o)';
1830 } else if(stats.passes) {
1840 return '( ^ .^)';
185 } else {
1860 return '( - .-)';
187 }
188}
189
190/**
191 * Move cursor up `n`.
192 *
193 * @param {Number} n
194 * @api private
195 */
196
1971NyanCat.prototype.cursorUp = function(n) {
1980 write('\u001b[' + n + 'A');
199};
200
201/**
202 * Move cursor down `n`.
203 *
204 * @param {Number} n
205 * @api private
206 */
207
2081NyanCat.prototype.cursorDown = function(n) {
2090 write('\u001b[' + n + 'B');
210};
211
212/**
213 * Generate rainbow colors.
214 *
215 * @return {Array}
216 * @api private
217 */
218
2191NyanCat.prototype.generateColors = function(){
2200 var colors = [];
221
2220 for (var i = 0; i < (6 * 7); i++) {
2230 var pi3 = Math.floor(Math.PI / 3);
2240 var n = (i * (1.0 / 6));
2250 var r = Math.floor(3 * Math.sin(n) + 3);
2260 var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);
2270 var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);
2280 colors.push(36 * r + 6 * g + b + 16);
229 }
230
2310 return colors;
232};
233
234/**
235 * Apply rainbow to the given `str`.
236 *
237 * @param {String} str
238 * @return {String}
239 * @api private
240 */
241
2421NyanCat.prototype.rainbowify = function(str){
2430 var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];
2440 this.colorIndex += 1;
2450 return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m';
246};
247
248/**
249 * Stdout helper.
250 */
251
2521function write(string) {
2530 process.stdout.write(string);
254}
255
256/**
257 * Inherit from `Base.prototype`.
258 */
259
2601NyanCat.prototype.__proto__ = Base.prototype;
261

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/progress.js

16%
30
5
25
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , cursor = Base.cursor
8 , color = Base.color;
9
10/**
11 * Expose `Progress`.
12 */
13
141exports = module.exports = Progress;
15
16/**
17 * General progress bar color.
18 */
19
201Base.colors.progress = 90;
21
22/**
23 * Initialize a new `Progress` bar test reporter.
24 *
25 * @param {Runner} runner
26 * @param {Object} options
27 * @api public
28 */
29
301function Progress(runner, options) {
310 Base.call(this, runner);
32
330 var self = this
34 , options = options || {}
35 , stats = this.stats
36 , width = Base.window.width * .50 | 0
37 , total = runner.total
38 , complete = 0
39 , max = Math.max;
40
41 // default chars
420 options.open = options.open || '[';
430 options.complete = options.complete || 'â–¬';
440 options.incomplete = options.incomplete || Base.symbols.dot;
450 options.close = options.close || ']';
460 options.verbose = false;
47
48 // tests started
490 runner.on('start', function(){
500 console.log();
510 cursor.hide();
52 });
53
54 // tests complete
550 runner.on('test end', function(){
560 complete++;
570 var incomplete = total - complete
58 , percent = complete / total
59 , n = width * percent | 0
60 , i = width - n;
61
620 cursor.CR();
630 process.stdout.write('\u001b[J');
640 process.stdout.write(color('progress', ' ' + options.open));
650 process.stdout.write(Array(n).join(options.complete));
660 process.stdout.write(Array(i).join(options.incomplete));
670 process.stdout.write(color('progress', options.close));
680 if (options.verbose) {
690 process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
70 }
71 });
72
73 // tests are complete, output some stats
74 // and the failures if any
750 runner.on('end', function(){
760 cursor.show();
770 console.log();
780 self.epilogue();
79 });
80}
81
82/**
83 * Inherit from `Base.prototype`.
84 */
85
861Progress.prototype.__proto__ = Base.prototype;
87

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/spec.js

83%
31
26
5
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , cursor = Base.cursor
8 , color = Base.color;
9
10/**
11 * Expose `Spec`.
12 */
13
141exports = module.exports = Spec;
15
16/**
17 * Initialize a new `Spec` test reporter.
18 *
19 * @param {Runner} runner
20 * @api public
21 */
22
231function Spec(runner) {
241 Base.call(this, runner);
25
261 var self = this
27 , stats = this.stats
28 , indents = 0
29 , n = 0;
30
311 function indent() {
326 return Array(indents).join(' ')
33 }
34
351 runner.on('start', function(){
361 console.log();
37 });
38
391 runner.on('suite', function(suite){
404 ++indents;
414 console.log(color('suite', '%s%s'), indent(), suite.title);
42 });
43
441 runner.on('suite end', function(suite){
454 --indents;
466 if (1 == indents) console.log();
47 });
48
491 runner.on('pending', function(test){
501 var fmt = indent() + color('pending', ' - %s');
511 console.log(fmt, test.title);
52 });
53
541 runner.on('pass', function(test){
551 if ('fast' == test.speed) {
561 var fmt = indent()
57 + color('checkmark', ' ' + Base.symbols.ok)
58 + color('pass', ' %s ');
591 cursor.CR();
601 console.log(fmt, test.title);
61 } else {
620 var fmt = indent()
63 + color('checkmark', ' ' + Base.symbols.ok)
64 + color('pass', ' %s ')
65 + color(test.speed, '(%dms)');
660 cursor.CR();
670 console.log(fmt, test.title, test.duration);
68 }
69 });
70
711 runner.on('fail', function(test, err){
720 cursor.CR();
730 console.log(indent() + color('fail', ' %d) %s'), ++n, test.title);
74 });
75
761 runner.on('end', self.epilogue.bind(self));
77}
78
79/**
80 * Inherit from `Base.prototype`.
81 */
82
831Spec.prototype.__proto__ = Base.prototype;
84

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/tap.js

16%
25
4
21
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , cursor = Base.cursor
8 , color = Base.color;
9
10/**
11 * Expose `TAP`.
12 */
13
141exports = module.exports = TAP;
15
16/**
17 * Initialize a new `TAP` reporter.
18 *
19 * @param {Runner} runner
20 * @api public
21 */
22
231function TAP(runner) {
240 Base.call(this, runner);
25
260 var self = this
27 , stats = this.stats
28 , n = 1
29 , passes = 0
30 , failures = 0;
31
320 runner.on('start', function(){
330 var total = runner.grepTotal(runner.suite);
340 console.log('%d..%d', 1, total);
35 });
36
370 runner.on('test end', function(){
380 ++n;
39 });
40
410 runner.on('pending', function(test){
420 console.log('ok %d %s # SKIP -', n, title(test));
43 });
44
450 runner.on('pass', function(test){
460 passes++;
470 console.log('ok %d %s', n, title(test));
48 });
49
500 runner.on('fail', function(test, err){
510 failures++;
520 console.log('not ok %d %s', n, title(test));
530 if (err.stack) console.log(err.stack.replace(/^/gm, ' '));
54 });
55
560 runner.on('end', function(){
570 console.log('# tests ' + (passes + failures));
580 console.log('# pass ' + passes);
590 console.log('# fail ' + failures);
60 });
61}
62
63/**
64 * Return a TAP-safe title of `test`
65 *
66 * @param {Object} test
67 * @return {String}
68 * @api private
69 */
70
711function title(test) {
720 return test.fullTitle().replace(/#/g, '');
73}
74

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/reporters/xunit.js

22%
35
8
27
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Base = require('./base')
7 , utils = require('../utils')
8 , escape = utils.escape;
9
10/**
11 * Save timer references to avoid Sinon interfering (see GH-237).
12 */
13
141var Date = global.Date
15 , setTimeout = global.setTimeout
16 , setInterval = global.setInterval
17 , clearTimeout = global.clearTimeout
18 , clearInterval = global.clearInterval;
19
20/**
21 * Expose `XUnit`.
22 */
23
241exports = module.exports = XUnit;
25
26/**
27 * Initialize a new `XUnit` reporter.
28 *
29 * @param {Runner} runner
30 * @api public
31 */
32
331function XUnit(runner) {
340 Base.call(this, runner);
350 var stats = this.stats
36 , tests = []
37 , self = this;
38
390 runner.on('pending', function(test){
400 tests.push(test);
41 });
42
430 runner.on('pass', function(test){
440 tests.push(test);
45 });
46
470 runner.on('fail', function(test){
480 tests.push(test);
49 });
50
510 runner.on('end', function(){
520 console.log(tag('testsuite', {
53 name: 'Mocha Tests'
54 , tests: stats.tests
55 , failures: stats.failures
56 , errors: stats.failures
57 , skipped: stats.tests - stats.failures - stats.passes
58 , timestamp: (new Date).toUTCString()
59 , time: (stats.duration / 1000) || 0
60 }, false));
61
620 tests.forEach(test);
630 console.log('</testsuite>');
64 });
65}
66
67/**
68 * Inherit from `Base.prototype`.
69 */
70
711XUnit.prototype.__proto__ = Base.prototype;
72
73/**
74 * Output tag for the given `test.`
75 */
76
771function test(test) {
780 var attrs = {
79 classname: test.parent.fullTitle()
80 , name: test.title
81 , time: (test.duration / 1000) || 0
82 };
83
840 if ('failed' == test.state) {
850 var err = test.err;
860 attrs.message = escape(err.message);
870 console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
880 } else if (test.pending) {
890 console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
90 } else {
910 console.log(tag('testcase', attrs, true) );
92 }
93}
94
95/**
96 * HTML tag helper.
97 */
98
991function tag(name, attrs, close, content) {
1000 var end = close ? '/>' : '>'
101 , pairs = []
102 , tag;
103
1040 for (var key in attrs) {
1050 pairs.push(key + '="' + escape(attrs[key]) + '"');
106 }
107
1080 tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
1090 if (content) tag += content + '</' + name + end;
1100 return tag;
111}
112
113/**
114 * Return cdata escaped CDATA `str`.
115 */
116
1171function cdata(str) {
1180 return '<![CDATA[' + escape(str) + ']]>';
119}
120

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/runnable.js

74%
81
60
21
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var EventEmitter = require('events').EventEmitter
7 , debug = require('debug')('mocha:runnable')
8 , milliseconds = require('./ms');
9
10/**
11 * Save timer references to avoid Sinon interfering (see GH-237).
12 */
13
141var Date = global.Date
15 , setTimeout = global.setTimeout
16 , setInterval = global.setInterval
17 , clearTimeout = global.clearTimeout
18 , clearInterval = global.clearInterval;
19
20/**
21 * Object#toString().
22 */
23
241var toString = Object.prototype.toString;
25
26/**
27 * Expose `Runnable`.
28 */
29
301module.exports = Runnable;
31
32/**
33 * Initialize a new `Runnable` with the given `title` and callback `fn`.
34 *
35 * @param {String} title
36 * @param {Function} fn
37 * @api private
38 */
39
401function Runnable(title, fn) {
414 this.title = title;
424 this.fn = fn;
434 this.async = fn && fn.length;
444 this.sync = ! this.async;
454 this._timeout = 2000;
464 this._slow = 75;
474 this.timedOut = false;
48}
49
50/**
51 * Inherit from `EventEmitter.prototype`.
52 */
53
541Runnable.prototype.__proto__ = EventEmitter.prototype;
55
56/**
57 * Set & get timeout `ms`.
58 *
59 * @param {Number|String} ms
60 * @return {Runnable|Number} ms or self
61 * @api private
62 */
63
641Runnable.prototype.timeout = function(ms){
6510 if (0 == arguments.length) return this._timeout;
664 if ('string' == typeof ms) ms = milliseconds(ms);
674 debug('timeout %d', ms);
684 this._timeout = ms;
694 if (this.timer) this.resetTimeout();
704 return this;
71};
72
73/**
74 * Set & get slow `ms`.
75 *
76 * @param {Number|String} ms
77 * @return {Runnable|Number} ms or self
78 * @api private
79 */
80
811Runnable.prototype.slow = function(ms){
828 if (0 === arguments.length) return this._slow;
834 if ('string' == typeof ms) ms = milliseconds(ms);
844 debug('timeout %d', ms);
854 this._slow = ms;
864 return this;
87};
88
89/**
90 * Return the full title generated by recursively
91 * concatenating the parent's full title.
92 *
93 * @return {String}
94 * @api public
95 */
96
971Runnable.prototype.fullTitle = function(){
989 return this.parent.fullTitle() + ' ' + this.title;
99};
100
101/**
102 * Clear the timeout.
103 *
104 * @api private
105 */
106
1071Runnable.prototype.clearTimeout = function(){
1081 clearTimeout(this.timer);
109};
110
111/**
112 * Inspect the runnable void of private properties.
113 *
114 * @return {String}
115 * @api private
116 */
117
1181Runnable.prototype.inspect = function(){
1190 return JSON.stringify(this, function(key, val){
1200 if ('_' == key[0]) return;
1210 if ('parent' == key) return '#<Suite>';
1220 if ('ctx' == key) return '#<Context>';
1230 return val;
124 }, 2);
125};
126
127/**
128 * Reset the timeout.
129 *
130 * @api private
131 */
132
1331Runnable.prototype.resetTimeout = function(){
1340 var self = this;
1350 var ms = this.timeout() || 1e9;
136
1370 this.clearTimeout();
1380 this.timer = setTimeout(function(){
1390 self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
1400 self.timedOut = true;
141 }, ms);
142};
143
144/**
145 * Whitelist these globals for this test run
146 *
147 * @api private
148 */
1491Runnable.prototype.globals = function(arr){
1500 var self = this;
1510 this._allowedGlobals = arr;
152};
153
154/**
155 * Run the test and invoke `fn(err)`.
156 *
157 * @param {Function} fn
158 * @api private
159 */
160
1611Runnable.prototype.run = function(fn){
1623 var self = this
163 , ms = this.timeout()
164 , start = new Date
165 , ctx = this.ctx
166 , finished
167 , emitted;
168
1696 if (ctx) ctx.runnable(this);
170
171 // timeout
1723 if (this.async) {
1731 if (ms) {
1741 this.timer = setTimeout(function(){
1750 done(new Error('timeout of ' + ms + 'ms exceeded'));
1760 self.timedOut = true;
177 }, ms);
178 }
179 }
180
181 // called multiple times
1823 function multiple(err) {
1830 if (emitted) return;
1840 emitted = true;
1850 self.emit('error', err || new Error('done() called multiple times'));
186 }
187
188 // finished
1893 function done(err) {
1901 if (self.timedOut) return;
1911 if (finished) return multiple(err);
1921 self.clearTimeout();
1931 self.duration = new Date - start;
1941 finished = true;
1951 fn(err);
196 }
197
198 // for .resetTimeout()
1993 this.callback = done;
200
201 // async
2023 if (this.async) {
2031 try {
2041 this.fn.call(ctx, function(err){
2051 if (err instanceof Error || toString.call(err) === "[object Error]") return done(err);
2061 if (null != err) return done(new Error('done() invoked with non-Error: ' + err));
2071 done();
208 });
209 } catch (err) {
2100 done(err);
211 }
2121 return;
213 }
214
2152 if (this.asyncOnly) {
2160 return done(new Error('--async-only option in use without declaring `done()`'));
217 }
218
219 // sync
2202 try {
2214 if (!this.pending) this.fn.call(ctx);
2222 this.duration = new Date - start;
2232 fn();
224 } catch (err) {
2250 fn(err);
226 }
227};
228

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/runner.js

79%
232
184
48
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var EventEmitter = require('events').EventEmitter
6 , debug = require('debug')('mocha:runner')
7 , Test = require('./test')
8 , utils = require('./utils')
9 , filter = utils.filter
10 , keys = utils.keys;
11
12/**
13 * Non-enumerable globals.
14 */
15
161var globals = [
17 'setTimeout',
18 'clearTimeout',
19 'setInterval',
20 'clearInterval',
21 'XMLHttpRequest',
22 'Date'
23];
24
25/**
26 * Expose `Runner`.
27 */
28
291module.exports = Runner;
30
31/**
32 * Initialize a `Runner` for the given `suite`.
33 *
34 * Events:
35 *
36 * - `start` execution started
37 * - `end` execution complete
38 * - `suite` (suite) test suite execution started
39 * - `suite end` (suite) all tests (and sub-suites) have finished
40 * - `test` (test) test execution started
41 * - `test end` (test) test completed
42 * - `hook` (hook) hook execution started
43 * - `hook end` (hook) hook complete
44 * - `pass` (test) test passed
45 * - `fail` (test, err) test failed
46 * - `pending` (test) test pending
47 *
48 * @api public
49 */
50
511function Runner(suite) {
522 var self = this;
532 this._globals = [];
542 this._abort = false;
552 this.suite = suite;
562 this.total = suite.total();
572 this.failures = 0;
584 this.on('test end', function(test){ self.checkGlobals(test); });
594 this.on('hook end', function(hook){ self.checkGlobals(hook); });
602 this.grep(/.*/);
612 this.globals(this.globalProps().concat(extraGlobals()));
62}
63
64/**
65 * Wrapper for setImmediate, process.nextTick, or browser polyfill.
66 *
67 * @param {Function} fn
68 * @api private
69 */
70
711Runner.immediately = global.setImmediate || process.nextTick;
72
73/**
74 * Inherit from `EventEmitter.prototype`.
75 */
76
771Runner.prototype.__proto__ = EventEmitter.prototype;
78
79/**
80 * Run tests with full titles matching `re`. Updates runner.total
81 * with number of tests matched.
82 *
83 * @param {RegExp} re
84 * @param {Boolean} invert
85 * @return {Runner} for chaining
86 * @api public
87 */
88
891Runner.prototype.grep = function(re, invert){
902 debug('grep %s', re);
912 this._grep = re;
922 this._invert = invert;
932 this.total = this.grepTotal(this.suite);
942 return this;
95};
96
97/**
98 * Returns the number of tests matching the grep search for the
99 * given suite.
100 *
101 * @param {Suite} suite
102 * @return {Number}
103 * @api public
104 */
105
1061Runner.prototype.grepTotal = function(suite) {
1077 var self = this;
1087 var total = 0;
109
1107 suite.eachTest(function(test){
1117 var match = self._grep.test(test.fullTitle());
1127 if (self._invert) match = !match;
11314 if (match) total++;
114 });
115
1167 return total;
117};
118
119/**
120 * Return a list of global properties.
121 *
122 * @return {Array}
123 * @api private
124 */
125
1261Runner.prototype.globalProps = function() {
1276 var props = utils.keys(global);
128
129 // non-enumerables
1306 for (var i = 0; i < globals.length; ++i) {
13160 if (~utils.indexOf(props, globals[i])) continue;
13212 props.push(globals[i]);
133 }
134
1356 return props;
136};
137
138/**
139 * Allow the given `arr` of globals.
140 *
141 * @param {Array} arr
142 * @return {Runner} for chaining
143 * @api public
144 */
145
1461Runner.prototype.globals = function(arr){
1473 if (0 == arguments.length) return this._globals;
1483 debug('globals %j', arr);
1493 this._globals = this._globals.concat(arr);
1503 return this;
151};
152
153/**
154 * Check for global variable leaks.
155 *
156 * @api private
157 */
158
1591Runner.prototype.checkGlobals = function(test){
1604 if (this.ignoreLeaks) return;
1614 var ok = this._globals;
162
1634 var globals = this.globalProps();
1644 var isNode = process.kill;
1654 var leaks;
166
1674 if (test) {
1684 ok = ok.concat(test._allowedGlobals || []);
169 }
170
1717 if(this.prevGlobalsLength == globals.length) return;
1721 this.prevGlobalsLength = globals.length;
173
1741 leaks = filterLeaks(ok, globals);
1751 this._globals = this._globals.concat(leaks);
176
1771 if (leaks.length > 1) {
1780 this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
1791 } else if (leaks.length) {
1800 this.fail(test, new Error('global leak detected: ' + leaks[0]));
181 }
182};
183
184/**
185 * Fail the given `test`.
186 *
187 * @param {Test} test
188 * @param {Error} err
189 * @api private
190 */
191
1921Runner.prototype.fail = function(test, err){
1930 ++this.failures;
1940 test.state = 'failed';
195
1960 if ('string' == typeof err) {
1970 err = new Error('the string "' + err + '" was thrown, throw an Error :)');
198 }
199
2000 this.emit('fail', test, err);
201};
202
203/**
204 * Fail the given `hook` with `err`.
205 *
206 * Hook failures work in the following pattern:
207 * - If bail, then exit
208 * - Failed `before` hook skips all tests in a suite and subsuites,
209 * but jumps to corresponding `after` hook
210 * - Failed `before each` hook skips remaining tests in a
211 * suite and jumps to corresponding `after each` hook,
212 * which is run only once
213 * - Failed `after` hook does not alter
214 * execution order
215 * - Failed `after each` hook skips remaining tests in a
216 * suite and subsuites, but executes other `after each`
217 * hooks
218 *
219 * @param {Hook} hook
220 * @param {Error} err
221 * @api private
222 */
223
2241Runner.prototype.failHook = function(hook, err){
2250 this.fail(hook, err);
2260 if (this.suite.bail()) {
2270 this.emit('end');
228 }
229};
230
231/**
232 * Run hook `name` callbacks and then invoke `fn()`.
233 *
234 * @param {String} name
235 * @param {Function} function
236 * @api private
237 */
238
2391Runner.prototype.hook = function(name, fn){
24014 var suite = this.suite
241 , hooks = suite['_' + name]
242 , self = this
243 , timer;
244
24514 function next(i) {
24616 var hook = hooks[i];
24730 if (!hook) return fn();
2482 if (self.failures && suite.bail()) return fn();
2492 self.currentRunnable = hook;
250
2512 hook.ctx.currentTest = self.test;
252
2532 self.emit('hook', hook);
254
2552 hook.on('error', function(err){
2560 self.failHook(hook, err);
257 });
258
2592 hook.run(function(err){
2602 hook.removeAllListeners('error');
2612 var testError = hook.error();
2622 if (testError) self.fail(self.test, testError);
2632 if (err) {
2640 self.failHook(hook, err);
265
266 // stop executing hooks, notify callee of hook err
2670 return fn(err);
268 }
2692 self.emit('hook end', hook);
2702 delete hook.ctx.currentTest;
2712 next(++i);
272 });
273 }
274
27514 Runner.immediately(function(){
27614 next(0);
277 });
278};
279
280/**
281 * Run hook `name` for the given array of `suites`
282 * in order, and callback `fn(err, errSuite)`.
283 *
284 * @param {String} name
285 * @param {Array} suites
286 * @param {Function} fn
287 * @api private
288 */
289
2901Runner.prototype.hooks = function(name, suites, fn){
2912 var self = this
292 , orig = this.suite;
293
2942 function next(suite) {
2958 self.suite = suite;
296
2978 if (!suite) {
2982 self.suite = orig;
2992 return fn();
300 }
301
3026 self.hook(name, function(err){
3036 if (err) {
3040 var errSuite = self.suite;
3050 self.suite = orig;
3060 return fn(err, errSuite);
307 }
308
3096 next(suites.pop());
310 });
311 }
312
3132 next(suites.pop());
314};
315
316/**
317 * Run hooks from the top level down.
318 *
319 * @param {String} name
320 * @param {Function} fn
321 * @api private
322 */
323
3241Runner.prototype.hookUp = function(name, fn){
3251 var suites = [this.suite].concat(this.parents()).reverse();
3261 this.hooks(name, suites, fn);
327};
328
329/**
330 * Run hooks from the bottom up.
331 *
332 * @param {String} name
333 * @param {Function} fn
334 * @api private
335 */
336
3371Runner.prototype.hookDown = function(name, fn){
3381 var suites = [this.suite].concat(this.parents());
3391 this.hooks(name, suites, fn);
340};
341
342/**
343 * Return an array of parent Suites from
344 * closest to furthest.
345 *
346 * @return {Array}
347 * @api private
348 */
349
3501Runner.prototype.parents = function(){
3512 var suite = this.suite
352 , suites = [];
3536 while (suite = suite.parent) suites.push(suite);
3542 return suites;
355};
356
357/**
358 * Run the current test and callback `fn(err)`.
359 *
360 * @param {Function} fn
361 * @api private
362 */
363
3641Runner.prototype.runTest = function(fn){
3651 var test = this.test
366 , self = this;
367
3681 if (this.asyncOnly) test.asyncOnly = true;
369
3701 try {
3711 test.on('error', function(err){
3720 self.fail(test, err);
373 });
3741 test.run(fn);
375 } catch (err) {
3760 fn(err);
377 }
378};
379
380/**
381 * Run tests in the given `suite` and invoke
382 * the callback `fn()` when complete.
383 *
384 * @param {Suite} suite
385 * @param {Function} fn
386 * @api private
387 */
388
3891Runner.prototype.runTests = function(suite, fn){
3904 var self = this
391 , tests = suite.tests.slice()
392 , test;
393
394
3954 function hookErr(err, errSuite, after) {
396 // before/after Each hook for errSuite failed:
3970 var orig = self.suite;
398
399 // for failed 'after each' hook start from errSuite parent,
400 // otherwise start from errSuite itself
4010 self.suite = after ? errSuite.parent : errSuite;
402
4030 if (self.suite) {
404 // call hookUp afterEach
4050 self.hookUp('afterEach', function(err2, errSuite2) {
4060 self.suite = orig;
407 // some hooks may fail even now
4080 if (err2) return hookErr(err2, errSuite2, true);
409 // report error suite
4100 fn(errSuite);
411 });
412 } else {
413 // there is no need calling other 'after each' hooks
4140 self.suite = orig;
4150 fn(errSuite);
416 }
417 }
418
4194 function next(err, errSuite) {
420 // if we bail after first err
4216 if (self.failures && suite._bail) return fn();
422
4236 if (self._abort) return fn();
424
4256 if (err) return hookErr(err, errSuite, true);
426
427 // next test
4286 test = tests.shift();
429
430 // all done
43110 if (!test) return fn();
432
433 // grep
4342 var match = self._grep.test(test.fullTitle());
4352 if (self._invert) match = !match;
4362 if (!match) return next();
437
438 // pending
4392 if (test.pending) {
4401 self.emit('pending', test);
4411 self.emit('test end', test);
4421 return next();
443 }
444
445 // execute test and hook(s)
4461 self.emit('test', self.test = test);
4471 self.hookDown('beforeEach', function(err, errSuite){
448
4491 if (err) return hookErr(err, errSuite, false);
450
4511 self.currentRunnable = self.test;
4521 self.runTest(function(err){
4531 test = self.test;
454
4551 if (err) {
4560 self.fail(test, err);
4570 self.emit('test end', test);
4580 return self.hookUp('afterEach', next);
459 }
460
4611 test.state = 'passed';
4621 self.emit('pass', test);
4631 self.emit('test end', test);
4641 self.hookUp('afterEach', next);
465 });
466 });
467 }
468
4694 this.next = next;
4704 next();
471};
472
473/**
474 * Run the given `suite` and invoke the
475 * callback `fn()` when complete.
476 *
477 * @param {Suite} suite
478 * @param {Function} fn
479 * @api private
480 */
481
4821Runner.prototype.runSuite = function(suite, fn){
4835 var total = this.grepTotal(suite)
484 , self = this
485 , i = 0;
486
4875 debug('run suite %s', suite.fullTitle());
488
4896 if (!total) return fn();
490
4914 this.emit('suite', this.suite = suite);
492
4934 function next(errSuite) {
4947 if (errSuite) {
495 // current suite failed on a hook from errSuite
4960 if (errSuite == suite) {
497 // if errSuite is current suite
498 // continue to the next sibling suite
4990 return done();
500 } else {
501 // errSuite is among the parents of current suite
502 // stop execution of errSuite and all sub-suites
5030 return done(errSuite);
504 }
505 }
506
5077 if (self._abort) return done();
508
5097 var curr = suite.suites[i++];
51011 if (!curr) return done();
5113 self.runSuite(curr, next);
512 }
513
5144 function done(errSuite) {
5154 self.suite = suite;
5164 self.hook('afterAll', function(){
5174 self.emit('suite end', suite);
5184 fn(errSuite);
519 });
520 }
521
5224 this.hook('beforeAll', function(err){
5234 if (err) return done();
5244 self.runTests(suite, next);
525 });
526};
527
528/**
529 * Handle uncaught exceptions.
530 *
531 * @param {Error} err
532 * @api private
533 */
534
5351Runner.prototype.uncaught = function(err){
5360 debug('uncaught exception %s', err.message);
5370 var runnable = this.currentRunnable;
5380 if (!runnable || 'failed' == runnable.state) return;
5390 runnable.clearTimeout();
5400 err.uncaught = true;
5410 this.fail(runnable, err);
542
543 // recover from test
5440 if ('test' == runnable.type) {
5450 this.emit('test end', runnable);
5460 this.hookUp('afterEach', this.next);
5470 return;
548 }
549
550 // bail on hooks
5510 this.emit('end');
552};
553
554/**
555 * Run the root suite and invoke `fn(failures)`
556 * on completion.
557 *
558 * @param {Function} fn
559 * @return {Runner} for chaining
560 * @api public
561 */
562
5631Runner.prototype.run = function(fn){
5642 var self = this
565 , fn = fn || function(){};
566
5672 function uncaught(err){
5680 self.uncaught(err);
569 }
570
5712 debug('start');
572
573 // callback
5742 this.on('end', function(){
5751 debug('end');
5761 process.removeListener('uncaughtException', uncaught);
5771 fn(self.failures);
578 });
579
580 // run suites
5812 this.emit('start');
5822 this.runSuite(this.suite, function(){
5832 debug('finished running');
5842 self.emit('end');
585 });
586
587 // uncaught exception
5881 process.on('uncaughtException', uncaught);
589
5901 return this;
591};
592
593/**
594 * Cleanly abort execution
595 *
596 * @return {Runner} for chaining
597 * @api public
598 */
5991Runner.prototype.abort = function(){
6000 debug('aborting');
6010 this._abort = true;
602}
603
604/**
605 * Filter leaks with the given globals flagged as `ok`.
606 *
607 * @param {Array} ok
608 * @param {Array} globals
609 * @return {Array}
610 * @api private
611 */
612
6131function filterLeaks(ok, globals) {
6141 return filter(globals, function(key){
615 // Firefox and Chrome exposes iframes as index inside the window object
61651 if (/^d+/.test(key)) return false;
617
618 // in firefox
619 // if runner runs in an iframe, this iframe's window.getInterface method not init at first
620 // it is assigned in some seconds
62149 if (global.navigator && /^getInterface/.test(key)) return false;
622
623 // an iframe could be approached by window[iframeIndex]
624 // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak
62549 if (global.navigator && /^\d+/.test(key)) return false;
626
627 // Opera and IE expose global variables for HTML element IDs (issue #243)
62849 if (/^mocha-/.test(key)) return false;
629
63049 var matched = filter(ok, function(ok){
6312499 if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);
6322499 return key == ok;
633 });
63449 return matched.length == 0 && (!global.navigator || 'onerror' !== key);
635 });
636}
637
638/**
639 * Array of globals dependent on the environment.
640 *
641 * @return {Array}
642 * @api private
643 */
644
6451 function extraGlobals() {
6462 if (typeof(process) === 'object' &&
647 typeof(process.version) === 'string') {
648
6492 var nodeVersion = process.version.split('.').reduce(function(a, v) {
6504 return a << 8 | v;
651 });
652
653 // 'errno' was renamed to process._errno in v0.9.11.
654
6552 if (nodeVersion < 0x00090B) {
6560 return ['errno'];
657 }
658 }
659
6602 return [];
661 }
662

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/suite.js

72%
118
85
33
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var EventEmitter = require('events').EventEmitter
7 , debug = require('debug')('mocha:suite')
8 , milliseconds = require('./ms')
9 , utils = require('./utils')
10 , Hook = require('./hook');
11
12/**
13 * Expose `Suite`.
14 */
15
161exports = module.exports = Suite;
17
18/**
19 * Create a new `Suite` with the given `title`
20 * and parent `Suite`. When a suite with the
21 * same title is already present, that suite
22 * is returned to provide nicer reporter
23 * and more flexible meta-testing.
24 *
25 * @param {Suite} parent
26 * @param {String} title
27 * @return {Suite}
28 * @api public
29 */
30
311exports.create = function(parent, title){
323 var suite = new Suite(title, parent.ctx);
333 suite.parent = parent;
343 if (parent.pending) suite.pending = true;
353 title = suite.fullTitle();
363 parent.addSuite(suite);
373 return suite;
38};
39
40/**
41 * Initialize a new `Suite` with the given
42 * `title` and `ctx`.
43 *
44 * @param {String} title
45 * @param {Context} ctx
46 * @api private
47 */
48
491function Suite(title, ctx) {
505 this.title = title;
515 this.ctx = ctx;
525 this.suites = [];
535 this.tests = [];
545 this.pending = false;
555 this._beforeEach = [];
565 this._beforeAll = [];
575 this._afterEach = [];
585 this._afterAll = [];
595 this.root = !title;
605 this._timeout = 2000;
615 this._slow = 75;
625 this._bail = false;
63}
64
65/**
66 * Inherit from `EventEmitter.prototype`.
67 */
68
691Suite.prototype.__proto__ = EventEmitter.prototype;
70
71/**
72 * Return a clone of this `Suite`.
73 *
74 * @return {Suite}
75 * @api private
76 */
77
781Suite.prototype.clone = function(){
790 var suite = new Suite(this.title);
800 debug('clone');
810 suite.ctx = this.ctx;
820 suite.timeout(this.timeout());
830 suite.slow(this.slow());
840 suite.bail(this.bail());
850 return suite;
86};
87
88/**
89 * Set timeout `ms` or short-hand such as "2s".
90 *
91 * @param {Number|String} ms
92 * @return {Suite|Number} for chaining
93 * @api private
94 */
95
961Suite.prototype.timeout = function(ms){
9718 if (0 == arguments.length) return this._timeout;
984 if ('string' == typeof ms) ms = milliseconds(ms);
994 debug('timeout %d', ms);
1004 this._timeout = parseInt(ms, 10);
1014 return this;
102};
103
104/**
105 * Set slow `ms` or short-hand such as "2s".
106 *
107 * @param {Number|String} ms
108 * @return {Suite|Number} for chaining
109 * @api private
110 */
111
1121Suite.prototype.slow = function(ms){
11317 if (0 === arguments.length) return this._slow;
1143 if ('string' == typeof ms) ms = milliseconds(ms);
1153 debug('slow %d', ms);
1163 this._slow = ms;
1173 return this;
118};
119
120/**
121 * Sets whether to bail after first error.
122 *
123 * @parma {Boolean} bail
124 * @return {Suite|Number} for chaining
125 * @api private
126 */
127
1281Suite.prototype.bail = function(bail){
12911 if (0 == arguments.length) return this._bail;
1305 debug('bail %s', bail);
1315 this._bail = bail;
1325 return this;
133};
134
135/**
136 * Run `fn(test[, done])` before running tests.
137 *
138 * @param {Function} fn
139 * @return {Suite} for chaining
140 * @api private
141 */
142
1431Suite.prototype.beforeAll = function(fn){
1440 if (this.pending) return this;
1450 var hook = new Hook('"before all" hook', fn);
1460 hook.parent = this;
1470 hook.timeout(this.timeout());
1480 hook.slow(this.slow());
1490 hook.ctx = this.ctx;
1500 this._beforeAll.push(hook);
1510 this.emit('beforeAll', hook);
1520 return this;
153};
154
155/**
156 * Run `fn(test[, done])` after running tests.
157 *
158 * @param {Function} fn
159 * @return {Suite} for chaining
160 * @api private
161 */
162
1631Suite.prototype.afterAll = function(fn){
1640 if (this.pending) return this;
1650 var hook = new Hook('"after all" hook', fn);
1660 hook.parent = this;
1670 hook.timeout(this.timeout());
1680 hook.slow(this.slow());
1690 hook.ctx = this.ctx;
1700 this._afterAll.push(hook);
1710 this.emit('afterAll', hook);
1720 return this;
173};
174
175/**
176 * Run `fn(test[, done])` before each test case.
177 *
178 * @param {Function} fn
179 * @return {Suite} for chaining
180 * @api private
181 */
182
1831Suite.prototype.beforeEach = function(fn){
1844 if (this.pending) return this;
1852 var hook = new Hook('"before each" hook', fn);
1862 hook.parent = this;
1872 hook.timeout(this.timeout());
1882 hook.slow(this.slow());
1892 hook.ctx = this.ctx;
1902 this._beforeEach.push(hook);
1912 this.emit('beforeEach', hook);
1922 return this;
193};
194
195/**
196 * Run `fn(test[, done])` after each test case.
197 *
198 * @param {Function} fn
199 * @return {Suite} for chaining
200 * @api private
201 */
202
2031Suite.prototype.afterEach = function(fn){
2042 if (this.pending) return this;
2050 var hook = new Hook('"after each" hook', fn);
2060 hook.parent = this;
2070 hook.timeout(this.timeout());
2080 hook.slow(this.slow());
2090 hook.ctx = this.ctx;
2100 this._afterEach.push(hook);
2110 this.emit('afterEach', hook);
2120 return this;
213};
214
215/**
216 * Add a test `suite`.
217 *
218 * @param {Suite} suite
219 * @return {Suite} for chaining
220 * @api private
221 */
222
2231Suite.prototype.addSuite = function(suite){
2243 suite.parent = this;
2253 suite.timeout(this.timeout());
2263 suite.slow(this.slow());
2273 suite.bail(this.bail());
2283 this.suites.push(suite);
2293 this.emit('suite', suite);
2303 return this;
231};
232
233/**
234 * Add a `test` to this suite.
235 *
236 * @param {Test} test
237 * @return {Suite} for chaining
238 * @api private
239 */
240
2411Suite.prototype.addTest = function(test){
2422 test.parent = this;
2432 test.timeout(this.timeout());
2442 test.slow(this.slow());
2452 test.ctx = this.ctx;
2462 this.tests.push(test);
2472 this.emit('test', test);
2482 return this;
249};
250
251/**
252 * Return the full title generated by recursively
253 * concatenating the parent's full title.
254 *
255 * @return {String}
256 * @api public
257 */
258
2591Suite.prototype.fullTitle = function(){
26039 if (this.parent) {
26122 var full = this.parent.fullTitle();
26229 if (full) return full + ' ' + this.title;
263 }
26432 return this.title;
265};
266
267/**
268 * Return the total number of tests.
269 *
270 * @return {Number}
271 * @api public
272 */
273
2741Suite.prototype.total = function(){
2755 return utils.reduce(this.suites, function(sum, suite){
2763 return sum + suite.total();
277 }, 0) + this.tests.length;
278};
279
280/**
281 * Iterates through each suite recursively to find
282 * all tests. Applies a function in the format
283 * `fn(test)`.
284 *
285 * @param {Function} fn
286 * @return {Suite}
287 * @api private
288 */
289
2901Suite.prototype.eachTest = function(fn){
29114 utils.forEach(this.tests, fn);
29214 utils.forEach(this.suites, function(suite){
2937 suite.eachTest(fn);
294 });
29514 return this;
296};
297

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/test.js

100%
7
7
0
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Runnable = require('./runnable');
7
8/**
9 * Expose `Test`.
10 */
11
121module.exports = Test;
13
14/**
15 * Initialize a new `Test` with the given `title` and callback `fn`.
16 *
17 * @param {String} title
18 * @param {Function} fn
19 * @api private
20 */
21
221function Test(title, fn) {
232 Runnable.call(this, title, fn);
242 this.pending = !fn;
252 this.type = 'test';
26}
27
28/**
29 * Inherit from `Runnable.prototype`.
30 */
31
321Test.prototype.__proto__ = Runnable.prototype;
33

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/lib/utils.js

46%
73
34
39
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var fs = require('fs')
6 , path = require('path')
7 , join = path.join
8 , debug = require('debug')('mocha:watch');
9
10/**
11 * Ignored directories.
12 */
13
141var ignore = ['node_modules', '.git'];
15
16/**
17 * Escape special characters in the given string of html.
18 *
19 * @param {String} html
20 * @return {String}
21 * @api private
22 */
23
241exports.escape = function(html){
250 return String(html)
26 .replace(/&/g, '&')
27 .replace(/"/g, '"')
28 .replace(/</g, '<')
29 .replace(/>/g, '>');
30};
31
32/**
33 * Array#forEach (<=IE8)
34 *
35 * @param {Array} array
36 * @param {Function} fn
37 * @param {Object} scope
38 * @api private
39 */
40
411exports.forEach = function(arr, fn, scope){
4228 for (var i = 0, l = arr.length; i < l; i++)
4314 fn.call(scope, arr[i], i);
44};
45
46/**
47 * Array#map (<=IE8)
48 *
49 * @param {Array} array
50 * @param {Function} fn
51 * @param {Object} scope
52 * @api private
53 */
54
551exports.map = function(arr, fn, scope){
560 var result = [];
570 for (var i = 0, l = arr.length; i < l; i++)
580 result.push(fn.call(scope, arr[i], i));
590 return result;
60};
61
62/**
63 * Array#indexOf (<=IE8)
64 *
65 * @parma {Array} arr
66 * @param {Object} obj to find index of
67 * @param {Number} start
68 * @api private
69 */
70
711exports.indexOf = function(arr, obj, start){
7236 for (var i = start || 0, l = arr.length; i < l; i++) {
731218 if (arr[i] === obj)
7424 return i;
75 }
7612 return -1;
77};
78
79/**
80 * Array#reduce (<=IE8)
81 *
82 * @param {Array} array
83 * @param {Function} fn
84 * @param {Object} initial value
85 * @api private
86 */
87
881exports.reduce = function(arr, fn, val){
895 var rval = val;
90
915 for (var i = 0, l = arr.length; i < l; i++) {
923 rval = fn(rval, arr[i], i, arr);
93 }
94
955 return rval;
96};
97
98/**
99 * Array#filter (<=IE8)
100 *
101 * @param {Array} array
102 * @param {Function} fn
103 * @api private
104 */
105
1061exports.filter = function(arr, fn){
10750 var ret = [];
108
10950 for (var i = 0, l = arr.length; i < l; i++) {
1102549 var val = arr[i];
1112598 if (fn(val, i, arr)) ret.push(val);
112 }
113
11450 return ret;
115};
116
117/**
118 * Object.keys (<=IE8)
119 *
120 * @param {Object} obj
121 * @return {Array} keys
122 * @api private
123 */
124
1251exports.keys = Object.keys || function(obj) {
1260 var keys = []
127 , has = Object.prototype.hasOwnProperty // for `window` on <=IE8
128
1290 for (var key in obj) {
1300 if (has.call(obj, key)) {
1310 keys.push(key);
132 }
133 }
134
1350 return keys;
136};
137
138/**
139 * Watch the given `files` for changes
140 * and invoke `fn(file)` on modification.
141 *
142 * @param {Array} files
143 * @param {Function} fn
144 * @api private
145 */
146
1471exports.watch = function(files, fn){
1480 var options = { interval: 100 };
1490 files.forEach(function(file){
1500 debug('file %s', file);
1510 fs.watchFile(file, options, function(curr, prev){
1520 if (prev.mtime < curr.mtime) fn(file);
153 });
154 });
155};
156
157/**
158 * Ignored files.
159 */
160
1611function ignored(path){
1620 return !~ignore.indexOf(path);
163}
164
165/**
166 * Lookup files in the given `dir`.
167 *
168 * @return {Array}
169 * @api private
170 */
171
1721exports.files = function(dir, ret){
1730 ret = ret || [];
174
1750 fs.readdirSync(dir)
176 .filter(ignored)
177 .forEach(function(path){
1780 path = join(dir, path);
1790 if (fs.statSync(path).isDirectory()) {
1800 exports.files(path, ret);
1810 } else if (path.match(/\.(js|coffee|litcoffee|coffee.md)$/)) {
1820 ret.push(path);
183 }
184 });
185
1860 return ret;
187};
188
189/**
190 * Compute a slug from the given `str`.
191 *
192 * @param {String} str
193 * @return {String}
194 * @api private
195 */
196
1971exports.slug = function(str){
1980 return str
199 .toLowerCase()
200 .replace(/ +/g, '-')
201 .replace(/[^-\w]/g, '');
202};
203
204/**
205 * Strip the function definition from `str`,
206 * and re-indent for pre whitespace.
207 */
208
2091exports.clean = function(str) {
2100 str = str
211 .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '')
212 .replace(/^function *\(.*\) *{/, '')
213 .replace(/\s+\}$/, '');
214
2150 var spaces = str.match(/^\n?( *)/)[1].length
216 , tabs = str.match(/^\n?(\t*)/)[1].length
217 , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm');
218
2190 str = str.replace(re, '');
220
2210 return exports.trim(str);
222};
223
224/**
225 * Escape regular expression characters in `str`.
226 *
227 * @param {String} str
228 * @return {String}
229 * @api private
230 */
231
2321exports.escapeRegexp = function(str){
2330 return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
234};
235
236/**
237 * Trim the given `str`.
238 *
239 * @param {String} str
240 * @return {String}
241 * @api private
242 */
243
2441exports.trim = function(str){
2450 return str.replace(/^\s+|\s+$/g, '');
246};
247
248/**
249 * Parse the given `qs`.
250 *
251 * @param {String} qs
252 * @return {Object}
253 * @api private
254 */
255
2561exports.parseQuery = function(qs){
2570 return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){
2580 var i = pair.indexOf('=')
259 , key = pair.slice(0, i)
260 , val = pair.slice(++i);
261
2620 obj[key] = decodeURIComponent(val);
2630 return obj;
264 }, {});
265};
266
267/**
268 * Highlight the given string of `js`.
269 *
270 * @param {String} js
271 * @return {String}
272 * @api private
273 */
274
2751function highlight(js) {
2760 return js
277 .replace(/</g, '<')
278 .replace(/>/g, '>')
279 .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
280 .replace(/('.*?')/gm, '<span class="string">$1</span>')
281 .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
282 .replace(/(\d+)/gm, '<span class="number">$1</span>')
283 .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
284 .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
285}
286
287/**
288 * Highlight the contents of tag `name`.
289 *
290 * @param {String} name
291 * @api private
292 */
293
2941exports.highlightTags = function(name) {
2950 var code = document.getElementsByTagName(name);
2960 for (var i = 0, len = code.length; i < len; ++i) {
2970 code[i].innerHTML = highlight(code[i].innerHTML);
298 }
299};
300

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/debug/lib/debug.js

47%
46
22
24
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var tty = require('tty');
6
7/**
8 * Expose `debug()` as the module.
9 */
10
111module.exports = debug;
12
13/**
14 * Enabled debuggers.
15 */
16
171var names = []
18 , skips = [];
19
201(process.env.DEBUG || '')
21 .split(/[\s,]+/)
22 .forEach(function(name){
231 name = name.replace('*', '.*?');
241 if (name[0] === '-') {
250 skips.push(new RegExp('^' + name.substr(1) + '$'));
26 } else {
271 names.push(new RegExp('^' + name + '$'));
28 }
29 });
30
31/**
32 * Colors.
33 */
34
351var colors = [6, 2, 3, 4, 5, 1];
36
37/**
38 * Previous debug() call.
39 */
40
411var prev = {};
42
43/**
44 * Previously assigned color.
45 */
46
471var prevColor = 0;
48
49/**
50 * Is stdout a TTY? Colored output is disabled when `true`.
51 */
52
531var isatty = tty.isatty(2);
54
55/**
56 * Select a color.
57 *
58 * @return {Number}
59 * @api private
60 */
61
621function color() {
630 return colors[prevColor++ % colors.length];
64}
65
66/**
67 * Humanize the given `ms`.
68 *
69 * @param {Number} m
70 * @return {String}
71 * @api private
72 */
73
741function humanize(ms) {
750 var sec = 1000
76 , min = 60 * 1000
77 , hour = 60 * min;
78
790 if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
800 if (ms >= min) return (ms / min).toFixed(1) + 'm';
810 if (ms >= sec) return (ms / sec | 0) + 's';
820 return ms + 'ms';
83}
84
85/**
86 * Create a debugger with the given `name`.
87 *
88 * @param {String} name
89 * @return {Type}
90 * @api public
91 */
92
931function debug(name) {
944 function disabled(){}
954 disabled.enabled = false;
96
974 var match = skips.some(function(re){
980 return re.test(name);
99 });
100
1014 if (match) return disabled;
102
1034 match = names.some(function(re){
1044 return re.test(name);
105 });
106
1078 if (!match) return disabled;
1080 var c = color();
109
1100 function colored(fmt) {
1110 fmt = coerce(fmt);
112
1130 var curr = new Date;
1140 var ms = curr - (prev[name] || curr);
1150 prev[name] = curr;
116
1170 fmt = ' \u001b[9' + c + 'm' + name + ' '
118 + '\u001b[3' + c + 'm\u001b[90m'
119 + fmt + '\u001b[3' + c + 'm'
120 + ' +' + humanize(ms) + '\u001b[0m';
121
1220 console.error.apply(this, arguments);
123 }
124
1250 function plain(fmt) {
1260 fmt = coerce(fmt);
127
1280 fmt = new Date().toUTCString()
129 + ' ' + name + ' ' + fmt;
1300 console.error.apply(this, arguments);
131 }
132
1330 colored.enabled = plain.enabled = true;
134
1350 return isatty || process.env.DEBUG_COLORS
136 ? colored
137 : plain;
138}
139
140/**
141 * Coerce `val`.
142 */
143
1441function coerce(val) {
1450 if (val instanceof Error) return val.stack || val.message;
1460 return val;
147}
148

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/compiler.js

57%
205
118
87
LineHitsSource
1
2/*!
3 * Jade - Compiler
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var nodes = require('./nodes')
13 , filters = require('./filters')
14 , doctypes = require('./doctypes')
15 , selfClosing = require('./self-closing')
16 , runtime = require('./runtime')
17 , utils = require('./utils');
18
19// if browser
20//
21// if (!Object.keys) {
22// Object.keys = function(obj){
23// var arr = [];
24// for (var key in obj) {
25// if (obj.hasOwnProperty(key)) {
26// arr.push(key);
27// }
28// }
29// return arr;
30// }
31// }
32//
33// if (!String.prototype.trimLeft) {
34// String.prototype.trimLeft = function(){
35// return this.replace(/^\s+/, '');
36// }
37// }
38//
39// end
40
41
42/**
43 * Initialize `Compiler` with the given `node`.
44 *
45 * @param {Node} node
46 * @param {Object} options
47 * @api public
48 */
49
501var Compiler = module.exports = function Compiler(node, options) {
511 this.options = options = options || {};
521 this.node = node;
531 this.hasCompiledDoctype = false;
541 this.hasCompiledTag = false;
551 this.pp = options.pretty || false;
561 this.debug = false !== options.compileDebug;
571 this.indents = 0;
581 this.parentIndents = 0;
591 if (options.doctype) this.setDoctype(options.doctype);
60};
61
62/**
63 * Compiler prototype.
64 */
65
661Compiler.prototype = {
67
68 /**
69 * Compile parse tree to JavaScript.
70 *
71 * @api public
72 */
73
74 compile: function(){
751 this.buf = ['var interp;'];
761 if (this.pp) this.buf.push("var __indent = [];");
771 this.lastBufferedIdx = -1;
781 this.visit(this.node);
791 return this.buf.join('\n');
80 },
81
82 /**
83 * Sets the default doctype `name`. Sets terse mode to `true` when
84 * html 5 is used, causing self-closing tags to end with ">" vs "/>",
85 * and boolean attributes are not mirrored.
86 *
87 * @param {string} name
88 * @api public
89 */
90
91 setDoctype: function(name){
921 var doctype = doctypes[(name || 'default').toLowerCase()];
931 doctype = doctype || '<!DOCTYPE ' + name + '>';
941 this.doctype = doctype;
951 this.terse = '5' == name || 'html' == name;
961 this.xml = 0 == this.doctype.indexOf('<?xml');
97 },
98
99 /**
100 * Buffer the given `str` optionally escaped.
101 *
102 * @param {String} str
103 * @param {Boolean} esc
104 * @api public
105 */
106
107 buffer: function(str, esc){
108445 if (esc) str = utils.escape(str);
109
110375 if (this.lastBufferedIdx == this.buf.length) {
111140 this.lastBuffered += str;
112140 this.buf[this.lastBufferedIdx - 1] = "buf.push('" + this.lastBuffered + "');"
113 } else {
114235 this.buf.push("buf.push('" + str + "');");
115235 this.lastBuffered = str;
116235 this.lastBufferedIdx = this.buf.length;
117 }
118 },
119
120 /**
121 * Buffer an indent based on the current `indent`
122 * property and an additional `offset`.
123 *
124 * @param {Number} offset
125 * @param {Boolean} newline
126 * @api public
127 */
128
129 prettyIndent: function(offset, newline){
1300 offset = offset || 0;
1310 newline = newline ? '\\n' : '';
1320 this.buffer(newline + Array(this.indents + offset).join(' '));
1330 if (this.parentIndents)
1340 this.buf.push("buf.push.apply(buf, __indent);");
135 },
136
137 /**
138 * Visit `node`.
139 *
140 * @param {Node} node
141 * @api public
142 */
143
144 visit: function(node){
145272 var debug = this.debug;
146
147272 if (debug) {
148272 this.buf.push('__jade.unshift({ lineno: ' + node.line
149 + ', filename: ' + (node.filename
150 ? JSON.stringify(node.filename)
151 : '__jade[0].filename')
152 + ' });');
153 }
154
155 // Massive hack to fix our context
156 // stack for - else[ if] etc
157272 if (false === node.debug && this.debug) {
1588 this.buf.pop();
1598 this.buf.pop();
160 }
161
162272 this.visitNode(node);
163
164544 if (debug) this.buf.push('__jade.shift();');
165 },
166
167 /**
168 * Visit `node`.
169 *
170 * @param {Node} node
171 * @api public
172 */
173
174 visitNode: function(node){
175272 var name = node.constructor.name
176 || node.constructor.toString().match(/function ([^(\s]+)()/)[1];
177272 return this['visit' + name](node);
178 },
179
180 /**
181 * Visit case `node`.
182 *
183 * @param {Literal} node
184 * @api public
185 */
186
187 visitCase: function(node){
1880 var _ = this.withinCase;
1890 this.withinCase = true;
1900 this.buf.push('switch (' + node.expr + '){');
1910 this.visit(node.block);
1920 this.buf.push('}');
1930 this.withinCase = _;
194 },
195
196 /**
197 * Visit when `node`.
198 *
199 * @param {Literal} node
200 * @api public
201 */
202
203 visitWhen: function(node){
2040 if ('default' == node.expr) {
2050 this.buf.push('default:');
206 } else {
2070 this.buf.push('case ' + node.expr + ':');
208 }
2090 this.visit(node.block);
2100 this.buf.push(' break;');
211 },
212
213 /**
214 * Visit literal `node`.
215 *
216 * @param {Literal} node
217 * @api public
218 */
219
220 visitLiteral: function(node){
2212 var str = node.str.replace(/\n/g, '\\\\n');
2222 this.buffer(str);
223 },
224
225 /**
226 * Visit all nodes in `block`.
227 *
228 * @param {Block} block
229 * @api public
230 */
231
232 visitBlock: function(block){
233126 var len = block.nodes.length
234 , escape = this.escape
235 , pp = this.pp
236
237 // Block keyword has a special meaning in mixins
238126 if (this.parentIndents && block.mode) {
2390 if (pp) this.buf.push("__indent.push('" + Array(this.indents + 1).join(' ') + "');")
2400 this.buf.push('block && block();');
2410 if (pp) this.buf.push("__indent.pop();")
2420 return;
243 }
244
245 // Pretty print multi-line text
246126 if (pp && len > 1 && !escape && block.nodes[0].isText && block.nodes[1].isText)
2470 this.prettyIndent(1, true);
248
249126 for (var i = 0; i < len; ++i) {
250 // Pretty print text
251147 if (pp && i > 0 && !escape && block.nodes[i].isText && block.nodes[i-1].isText)
2520 this.prettyIndent(1, false);
253
254147 this.visit(block.nodes[i]);
255 // Multiple text nodes are separated by newlines
256147 if (block.nodes[i+1] && block.nodes[i].isText && block.nodes[i+1].isText)
2570 this.buffer('\\n');
258 }
259 },
260
261 /**
262 * Visit `doctype`. Sets terse mode to `true` when html 5
263 * is used, causing self-closing tags to end with ">" vs "/>",
264 * and boolean attributes are not mirrored.
265 *
266 * @param {Doctype} doctype
267 * @api public
268 */
269
270 visitDoctype: function(doctype){
2711 if (doctype && (doctype.val || !this.doctype)) {
2721 this.setDoctype(doctype.val || 'default');
273 }
274
2752 if (this.doctype) this.buffer(this.doctype);
2761 this.hasCompiledDoctype = true;
277 },
278
279 /**
280 * Visit `mixin`, generating a function that
281 * may be called within the template.
282 *
283 * @param {Mixin} mixin
284 * @api public
285 */
286
287 visitMixin: function(mixin){
2880 var name = mixin.name.replace(/-/g, '_') + '_mixin'
289 , args = mixin.args || ''
290 , block = mixin.block
291 , attrs = mixin.attrs
292 , pp = this.pp;
293
2940 if (mixin.call) {
2950 if (pp) this.buf.push("__indent.push('" + Array(this.indents + 1).join(' ') + "');")
2960 if (block || attrs.length) {
297
2980 this.buf.push(name + '.call({');
299
3000 if (block) {
3010 this.buf.push('block: function(){');
302
303 // Render block with no indents, dynamically added when rendered
3040 this.parentIndents++;
3050 var _indents = this.indents;
3060 this.indents = 0;
3070 this.visit(mixin.block);
3080 this.indents = _indents;
3090 this.parentIndents--;
310
3110 if (attrs.length) {
3120 this.buf.push('},');
313 } else {
3140 this.buf.push('}');
315 }
316 }
317
3180 if (attrs.length) {
3190 var val = this.attrs(attrs);
3200 if (val.inherits) {
3210 this.buf.push('attributes: merge({' + val.buf
322 + '}, attributes), escaped: merge(' + val.escaped + ', escaped, true)');
323 } else {
3240 this.buf.push('attributes: {' + val.buf + '}, escaped: ' + val.escaped);
325 }
326 }
327
3280 if (args) {
3290 this.buf.push('}, ' + args + ');');
330 } else {
3310 this.buf.push('});');
332 }
333
334 } else {
3350 this.buf.push(name + '(' + args + ');');
336 }
3370 if (pp) this.buf.push("__indent.pop();")
338 } else {
3390 this.buf.push('var ' + name + ' = function(' + args + '){');
3400 this.buf.push('var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {};');
3410 this.parentIndents++;
3420 this.visit(block);
3430 this.parentIndents--;
3440 this.buf.push('};');
345 }
346 },
347
348 /**
349 * Visit `tag` buffering tag markup, generating
350 * attributes, visiting the `tag`'s code and block.
351 *
352 * @param {Tag} tag
353 * @api public
354 */
355
356 visitTag: function(tag){
357102 this.indents++;
358102 var name = tag.name
359 , pp = this.pp;
360
361102 if (tag.buffer) name = "' + (" + name + ") + '";
362
363102 if (!this.hasCompiledTag) {
3641 if (!this.hasCompiledDoctype && 'html' == name) {
3650 this.visitDoctype();
366 }
3671 this.hasCompiledTag = true;
368 }
369
370 // pretty print
371102 if (pp && !tag.isInline())
3720 this.prettyIndent(0, true);
373
374102 if ((~selfClosing.indexOf(name) || tag.selfClosing) && !this.xml) {
3750 this.buffer('<' + name);
3760 this.visitAttributes(tag.attrs);
3770 this.terse
378 ? this.buffer('>')
379 : this.buffer('/>');
380 } else {
381 // Optimize attributes buffering
382102 if (tag.attrs.length) {
38379 this.buffer('<' + name);
384158 if (tag.attrs.length) this.visitAttributes(tag.attrs);
38579 this.buffer('>');
386 } else {
38723 this.buffer('<' + name + '>');
388 }
389145 if (tag.code) this.visitCode(tag.code);
390102 this.escape = 'pre' == tag.name;
391102 this.visit(tag.block);
392
393 // pretty print
394102 if (pp && !tag.isInline() && 'pre' != tag.name && !tag.canInline())
3950 this.prettyIndent(0, true);
396
397102 this.buffer('</' + name + '>');
398 }
399102 this.indents--;
400 },
401
402 /**
403 * Visit `filter`, throwing when the filter does not exist.
404 *
405 * @param {Filter} filter
406 * @api public
407 */
408
409 visitFilter: function(filter){
4100 var fn = filters[filter.name];
411
412 // unknown filter
4130 if (!fn) {
4140 if (filter.isASTFilter) {
4150 throw new Error('unknown ast filter "' + filter.name + ':"');
416 } else {
4170 throw new Error('unknown filter ":' + filter.name + '"');
418 }
419 }
420
4210 if (filter.isASTFilter) {
4220 this.buf.push(fn(filter.block, this, filter.attrs));
423 } else {
4240 var text = filter.block.nodes.map(function(node){ return node.val }).join('\n');
4250 filter.attrs = filter.attrs || {};
4260 filter.attrs.filename = this.options.filename;
4270 this.buffer(utils.text(fn(text, filter.attrs)));
428 }
429 },
430
431 /**
432 * Visit `text` node.
433 *
434 * @param {Text} text
435 * @api public
436 */
437
438 visitText: function(text){
43919 text = utils.text(text.val.replace(/\\/g, '\\\\'));
44019 if (this.escape) text = escape(text);
44119 this.buffer(text);
442 },
443
444 /**
445 * Visit a `comment`, only buffering when the buffer flag is set.
446 *
447 * @param {Comment} comment
448 * @api public
449 */
450
451 visitComment: function(comment){
4520 if (!comment.buffer) return;
4530 if (this.pp) this.prettyIndent(1, true);
4540 this.buffer('<!--' + utils.escape(comment.val) + '-->');
455 },
456
457 /**
458 * Visit a `BlockComment`.
459 *
460 * @param {Comment} comment
461 * @api public
462 */
463
464 visitBlockComment: function(comment){
4650 if (!comment.buffer) return;
4660 if (0 == comment.val.trim().indexOf('if')) {
4670 this.buffer('<!--[' + comment.val.trim() + ']>');
4680 this.visit(comment.block);
4690 this.buffer('<![endif]-->');
470 } else {
4710 this.buffer('<!--' + comment.val);
4720 this.visit(comment.block);
4730 this.buffer('-->');
474 }
475 },
476
477 /**
478 * Visit `code`, respecting buffer / escape flags.
479 * If the code is followed by a block, wrap it in
480 * a self-calling function.
481 *
482 * @param {Code} code
483 * @api public
484 */
485
486 visitCode: function(code){
487 // Wrap code blocks with {}.
488 // we only wrap unbuffered code blocks ATM
489 // since they are usually flow control
490
491 // Buffer code
49261 if (code.buffer) {
49343 var val = code.val.trimLeft();
49443 this.buf.push('var __val__ = ' + val);
49543 val = 'null == __val__ ? "" : __val__';
49686 if (code.escape) val = 'escape(' + val + ')';
49743 this.buf.push("buf.push(" + val + ");");
498 } else {
49918 this.buf.push(code.val);
500 }
501
502 // Block support
50361 if (code.block) {
50428 if (!code.buffer) this.buf.push('{');
50514 this.visit(code.block);
50628 if (!code.buffer) this.buf.push('}');
507 }
508 },
509
510 /**
511 * Visit `each` block.
512 *
513 * @param {Each} each
514 * @api public
515 */
516
517 visitEach: function(each){
5184 this.buf.push(''
519 + '// iterate ' + each.obj + '\n'
520 + ';(function(){\n'
521 + ' if (\'number\' == typeof ' + each.obj + '.length) {\n'
522 + ' for (var ' + each.key + ' = 0, $$l = ' + each.obj + '.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n'
523 + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n');
524
5254 this.visit(each.block);
526
5274 this.buf.push(''
528 + ' }\n'
529 + ' } else {\n'
530 + ' for (var ' + each.key + ' in ' + each.obj + ') {\n'
531 // if browser
532 // + ' if (' + each.obj + '.hasOwnProperty(' + each.key + ')){'
533 // end
534 + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n');
535
5364 this.visit(each.block);
537
538 // if browser
539 // this.buf.push(' }\n');
540 // end
541
5424 this.buf.push(' }\n }\n}).call(this);\n');
543 },
544
545 /**
546 * Visit `attrs`.
547 *
548 * @param {Array} attrs
549 * @api public
550 */
551
552 visitAttributes: function(attrs){
55379 var val = this.attrs(attrs);
55479 if (val.inherits) {
5550 this.buf.push("buf.push(attrs(merge({ " + val.buf +
556 " }, attributes), merge(" + val.escaped + ", escaped, true)));");
55779 } else if (val.constant) {
55870 eval('var buf={' + val.buf + '};');
55970 this.buffer(runtime.attrs(buf, JSON.parse(val.escaped)), true);
560 } else {
5619 this.buf.push("buf.push(attrs({ " + val.buf + " }, " + val.escaped + "));");
562 }
563 },
564
565 /**
566 * Compile attributes.
567 */
568
569 attrs: function(attrs){
57079 var buf = []
571 , classes = []
572 , escaped = {}
57385 , constant = attrs.every(function(attr){ return isConstant(attr.val) })
574 , inherits = false;
575
576158 if (this.terse) buf.push('terse: true');
577
57879 attrs.forEach(function(attr){
57985 if (attr.name == 'attributes') return inherits = true;
58085 escaped[attr.name] = attr.escaped;
58185 if (attr.name == 'class') {
58269 classes.push('(' + attr.val + ')');
583 } else {
58416 var pair = "'" + attr.name + "':(" + attr.val + ')';
58516 buf.push(pair);
586 }
587 });
588
58979 if (classes.length) {
59067 classes = classes.join(" + ' ' + ");
59167 buf.push("class: " + classes);
592 }
593
59479 return {
595 buf: buf.join(', ').replace('class:', '"class":'),
596 escaped: JSON.stringify(escaped),
597 inherits: inherits,
598 constant: constant
599 };
600 }
601};
602
603/**
604 * Check if expression can be evaluated to a constant
605 *
606 * @param {String} expression
607 * @return {Boolean}
608 * @api private
609 */
610
6111function isConstant(val){
612 // Check strings/literals
61385 if (/^ *("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|true|false|null|undefined) *$/i.test(val))
61476 return true;
615
616 // Check numbers
6179 if (!isNaN(Number(val)))
6180 return true;
619
620 // Check arrays
6219 var matches;
6229 if (matches = /^ *\[(.*)\] *$/.exec(val))
6230 return matches[1].split(',').every(isConstant);
624
6259 return false;
626}
627
628/**
629 * Escape the given string of `html`.
630 *
631 * @param {String} html
632 * @return {String}
633 * @api private
634 */
635
6361function escape(html){
6370 return String(html)
638 .replace(/&(?!\w+;)/g, '&')
639 .replace(/</g, '<')
640 .replace(/>/g, '>')
641 .replace(/"/g, '"');
642}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/doctypes.js

100%
1
1
0
LineHitsSource
1
2/*!
3 * Jade - doctypes
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
81module.exports = {
9 '5': '<!DOCTYPE html>'
10 , 'default': '<!DOCTYPE html>'
11 , 'xml': '<?xml version="1.0" encoding="utf-8" ?>'
12 , 'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
13 , 'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
14 , 'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'
15 , '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
16 , 'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">'
17 , 'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
18};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/filters.js

3%
33
1
32
LineHitsSource
1
2/*!
3 * Jade - filters
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
81module.exports = {
9
10 /**
11 * Wrap text with CDATA block.
12 */
13
14 cdata: function(str){
150 return '<![CDATA[\\n' + str + '\\n]]>';
16 },
17
18 /**
19 * Transform sass to css, wrapped in style tags.
20 */
21
22 sass: function(str){
230 str = str.replace(/\\n/g, '\n');
240 var sass = require('sass').render(str).replace(/\n/g, '\\n');
250 return '<style type="text/css">' + sass + '</style>';
26 },
27
28 /**
29 * Transform stylus to css, wrapped in style tags.
30 */
31
32 stylus: function(str, options){
330 var ret;
340 str = str.replace(/\\n/g, '\n');
350 var stylus = require('stylus');
360 stylus(str, options).render(function(err, css){
370 if (err) throw err;
380 ret = css.replace(/\n/g, '\\n');
39 });
400 return '<style type="text/css">' + ret + '</style>';
41 },
42
43 /**
44 * Transform less to css, wrapped in style tags.
45 */
46
47 less: function(str){
480 var ret;
490 str = str.replace(/\\n/g, '\n');
500 require('less').render(str, function(err, css){
510 if (err) throw err;
520 ret = '<style type="text/css">' + css.replace(/\n/g, '\\n') + '</style>';
53 });
540 return ret;
55 },
56
57 /**
58 * Transform markdown to html.
59 */
60
61 markdown: function(str){
620 var md;
63
64 // support markdown / discount
650 try {
660 md = require('markdown');
67 } catch (err){
680 try {
690 md = require('discount');
70 } catch (err) {
710 try {
720 md = require('markdown-js');
73 } catch (err) {
740 try {
750 md = require('marked');
76 } catch (err) {
770 throw new
78 Error('Cannot find markdown library, install markdown, discount, or marked.');
79 }
80 }
81 }
82 }
83
840 str = str.replace(/\\n/g, '\n');
850 return md.parse(str).replace(/\n/g, '\\n').replace(/'/g,''');
86 },
87
88 /**
89 * Transform coffeescript to javascript.
90 */
91
92 coffeescript: function(str){
930 str = str.replace(/\\n/g, '\n');
940 var js = require('coffee-script').compile(str).replace(/\\/g, '\\\\').replace(/\n/g, '\\n');
950 return '<script type="text/javascript">\\n' + js + '</script>';
96 }
97};
98

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/inline-tags.js

100%
1
1
0
LineHitsSource
1
2/*!
3 * Jade - inline tags
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
81module.exports = [
9 'a'
10 , 'abbr'
11 , 'acronym'
12 , 'b'
13 , 'br'
14 , 'code'
15 , 'em'
16 , 'font'
17 , 'i'
18 , 'img'
19 , 'ins'
20 , 'kbd'
21 , 'map'
22 , 'samp'
23 , 'small'
24 , 'span'
25 , 'strong'
26 , 'sub'
27 , 'sup'
28];

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/jade.js

55%
52
29
23
LineHitsSource
1/*!
2 * Jade
3 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
4 * MIT Licensed
5 */
6
7/**
8 * Module dependencies.
9 */
10
111var Parser = require('./parser')
12 , Lexer = require('./lexer')
13 , Compiler = require('./compiler')
14 , runtime = require('./runtime')
15// if node
16 , fs = require('fs');
17// end
18
19/**
20 * Library version.
21 */
22
231exports.version = '0.26.3';
24
25/**
26 * Expose self closing tags.
27 */
28
291exports.selfClosing = require('./self-closing');
30
31/**
32 * Default supported doctypes.
33 */
34
351exports.doctypes = require('./doctypes');
36
37/**
38 * Text filters.
39 */
40
411exports.filters = require('./filters');
42
43/**
44 * Utilities.
45 */
46
471exports.utils = require('./utils');
48
49/**
50 * Expose `Compiler`.
51 */
52
531exports.Compiler = Compiler;
54
55/**
56 * Expose `Parser`.
57 */
58
591exports.Parser = Parser;
60
61/**
62 * Expose `Lexer`.
63 */
64
651exports.Lexer = Lexer;
66
67/**
68 * Nodes.
69 */
70
711exports.nodes = require('./nodes');
72
73/**
74 * Jade runtime helpers.
75 */
76
771exports.runtime = runtime;
78
79/**
80 * Template function cache.
81 */
82
831exports.cache = {};
84
85/**
86 * Parse the given `str` of jade and return a function body.
87 *
88 * @param {String} str
89 * @param {Object} options
90 * @return {String}
91 * @api private
92 */
93
941function parse(str, options){
951 try {
96 // Parse
971 var parser = new Parser(str, options.filename, options);
98
99 // Compile
1001 var compiler = new (options.compiler || Compiler)(parser.parse(), options)
101 , js = compiler.compile();
102
103 // Debug compiler
1041 if (options.debug) {
1050 console.error('\nCompiled Function:\n\n\033[90m%s\033[0m', js.replace(/^/gm, ' '));
106 }
107
1081 return ''
109 + 'var buf = [];\n'
110 + (options.self
111 ? 'var self = locals || {};\n' + js
112 : 'with (locals || {}) {\n' + js + '\n}\n')
113 + 'return buf.join("");';
114 } catch (err) {
1150 parser = parser.context();
1160 runtime.rethrow(err, parser.filename, parser.lexer.lineno);
117 }
118}
119
120/**
121 * Compile a `Function` representation of the given jade `str`.
122 *
123 * Options:
124 *
125 * - `compileDebug` when `false` debugging code is stripped from the compiled template
126 * - `client` when `true` the helper functions `escape()` etc will reference `jade.escape()`
127 * for use with the Jade client-side runtime.js
128 *
129 * @param {String} str
130 * @param {Options} options
131 * @return {Function}
132 * @api public
133 */
134
1351exports.compile = function(str, options){
1361 var options = options || {}
137 , client = options.client
138 , filename = options.filename
139 ? JSON.stringify(options.filename)
140 : 'undefined'
141 , fn;
142
1431 if (options.compileDebug !== false) {
1441 fn = [
145 'var __jade = [{ lineno: 1, filename: ' + filename + ' }];'
146 , 'try {'
147 , parse(String(str), options)
148 , '} catch (err) {'
149 , ' rethrow(err, __jade[0].filename, __jade[0].lineno);'
150 , '}'
151 ].join('\n');
152 } else {
1530 fn = parse(String(str), options);
154 }
155
1561 if (client) {
1570 fn = 'attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n' + fn;
158 }
159
1601 fn = new Function('locals, attrs, escape, rethrow, merge', fn);
161
1621 if (client) return fn;
163
1641 return function(locals){
1650 return fn(locals, runtime.attrs, runtime.escape, runtime.rethrow, runtime.merge);
166 };
167};
168
169/**
170 * Render the given `str` of jade and invoke
171 * the callback `fn(err, str)`.
172 *
173 * Options:
174 *
175 * - `cache` enable template caching
176 * - `filename` filename required for `include` / `extends` and caching
177 *
178 * @param {String} str
179 * @param {Object|Function} options or fn
180 * @param {Function} fn
181 * @api public
182 */
183
1841exports.render = function(str, options, fn){
185 // swap args
1860 if ('function' == typeof options) {
1870 fn = options, options = {};
188 }
189
190 // cache requires .filename
1910 if (options.cache && !options.filename) {
1920 return fn(new Error('the "filename" option is required for caching'));
193 }
194
1950 try {
1960 var path = options.filename;
1970 var tmpl = options.cache
198 ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options))
199 : exports.compile(str, options);
2000 fn(null, tmpl(options));
201 } catch (err) {
2020 fn(err);
203 }
204};
205
206/**
207 * Render a Jade file at the given `path` and callback `fn(err, str)`.
208 *
209 * @param {String} path
210 * @param {Object|Function} options or callback
211 * @param {Function} fn
212 * @api public
213 */
214
2151exports.renderFile = function(path, options, fn){
2160 var key = path + ':string';
217
2180 if ('function' == typeof options) {
2190 fn = options, options = {};
220 }
221
2220 try {
2230 options.filename = path;
2240 var str = options.cache
225 ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8'))
226 : fs.readFileSync(path, 'utf8');
2270 exports.render(str, options, fn);
228 } catch (err) {
2290 fn(err);
230 }
231};
232
233/**
234 * Express support.
235 */
236
2371exports.__express = exports.renderFile;
238

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/lexer.js

75%
259
195
64
LineHitsSource
1
2/*!
3 * Jade - Lexer
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Initialize `Lexer` with the given `str`.
10 *
11 * Options:
12 *
13 * - `colons` allow colons for attr delimiters
14 *
15 * @param {String} str
16 * @param {Object} options
17 * @api private
18 */
19
201var Lexer = module.exports = function Lexer(str, options) {
212 options = options || {};
222 this.input = str.replace(/\r\n|\r/g, '\n');
232 this.colons = options.colons;
242 this.deferredTokens = [];
252 this.lastIndents = 0;
262 this.lineno = 1;
272 this.stash = [];
282 this.indentStack = [];
292 this.indentRe = null;
302 this.pipeless = false;
31};
32
33/**
34 * Lexer prototype.
35 */
36
371Lexer.prototype = {
38
39 /**
40 * Construct a token with the given `type` and `val`.
41 *
42 * @param {String} type
43 * @param {String} val
44 * @return {Object}
45 * @api private
46 */
47
48 tok: function(type, val){
49202 return {
50 type: type
51 , line: this.lineno
52 , val: val
53 }
54 },
55
56 /**
57 * Consume the given `len` of input.
58 *
59 * @param {Number} len
60 * @api private
61 */
62
63 consume: function(len){
64174 this.input = this.input.substr(len);
65 },
66
67 /**
68 * Scan for `type` with the given `regexp`.
69 *
70 * @param {String} type
71 * @param {RegExp} regexp
72 * @return {Object}
73 * @api private
74 */
75
76 scan: function(regexp, type){
771549 var captures;
781549 if (captures = regexp.exec(this.input)) {
7946 this.consume(captures[0].length);
8046 return this.tok(type, captures[1]);
81 }
82 },
83
84 /**
85 * Defer the given `tok`.
86 *
87 * @param {Object} tok
88 * @api private
89 */
90
91 defer: function(tok){
9228 this.deferredTokens.push(tok);
93 },
94
95 /**
96 * Lookahead `n` tokens.
97 *
98 * @param {Number} n
99 * @return {Object}
100 * @api private
101 */
102
103 lookahead: function(n){
104798 var fetch = n - this.stash.length;
105999 while (fetch-- > 0) this.stash.push(this.next());
106798 return this.stash[--n];
107 },
108
109 /**
110 * Return the indexOf `start` / `end` delimiters.
111 *
112 * @param {String} start
113 * @param {String} end
114 * @return {Number}
115 * @api private
116 */
117
118 indexOfDelimiters: function(start, end){
1197 var str = this.input
120 , nstart = 0
121 , nend = 0
122 , pos = 0;
1237 for (var i = 0, len = str.length; i < len; ++i) {
124213 if (start == str.charAt(i)) {
12510 ++nstart;
126203 } else if (end == str.charAt(i)) {
12710 if (++nend == nstart) {
1287 pos = i;
1297 break;
130 }
131 }
132 }
1337 return pos;
134 },
135
136 /**
137 * Stashed token.
138 */
139
140 stashed: function() {
141214 return this.stash.length
142 && this.stash.shift();
143 },
144
145 /**
146 * Deferred token.
147 */
148
149 deferred: function() {
150204 return this.deferredTokens.length
151 && this.deferredTokens.shift();
152 },
153
154 /**
155 * end-of-source.
156 */
157
158 eos: function() {
159344 if (this.input.length) return;
1602 if (this.indentStack.length) {
1610 this.indentStack.shift();
1620 return this.tok('outdent');
163 } else {
1642 return this.tok('eos');
165 }
166 },
167
168 /**
169 * Blank line.
170 */
171
172 blank: function() {
173176 var captures;
174176 if (captures = /^\n *\n/.exec(this.input)) {
1753 this.consume(captures[0].length - 1);
1763 if (this.pipeless) return this.tok('text', '');
1773 return this.next();
178 }
179 },
180
181 /**
182 * Comment.
183 */
184
185 comment: function() {
18611 var captures;
18711 if (captures = /^ *\/\/(-)?([^\n]*)/.exec(this.input)) {
1880 this.consume(captures[0].length);
1890 var tok = this.tok('comment', captures[2]);
1900 tok.buffer = '-' != captures[1];
1910 return tok;
192 }
193 },
194
195 /**
196 * Interpolated tag.
197 */
198
199 interpolation: function() {
200170 var captures;
201170 if (captures = /^#\{(.*?)\}/.exec(this.input)) {
2020 this.consume(captures[0].length);
2030 return this.tok('interpolation', captures[1]);
204 }
205 },
206
207 /**
208 * Tag.
209 */
210
211 tag: function() {
212158 var captures;
213158 if (captures = /^(\w[-:\w]*)(\/?)/.exec(this.input)) {
21433 this.consume(captures[0].length);
21533 var tok, name = captures[1];
21633 if (':' == name[name.length - 1]) {
2170 name = name.slice(0, -1);
2180 tok = this.tok('tag', name);
2190 this.defer(this.tok(':'));
2200 while (' ' == this.input[0]) this.input = this.input.substr(1);
221 } else {
22233 tok = this.tok('tag', name);
223 }
22433 tok.selfClosing = !! captures[2];
22533 return tok;
226 }
227 },
228
229 /**
230 * Filter.
231 */
232
233 filter: function() {
234125 return this.scan(/^:(\w+)/, 'filter');
235 },
236
237 /**
238 * Doctype.
239 */
240
241 doctype: function() {
242171 return this.scan(/^(?:!!!|doctype) *([^\n]+)?/, 'doctype');
243 },
244
245 /**
246 * Id.
247 */
248
249 id: function() {
250109 return this.scan(/^#([\w-]+)/, 'id');
251 },
252
253 /**
254 * Class.
255 */
256
257 className: function() {
258101 return this.scan(/^\.([\w-]+)/, 'class');
259 },
260
261 /**
262 * Text.
263 */
264
265 text: function() {
26611 return this.scan(/^(?:\| ?| ?)?([^\n]+)/, 'text');
267 },
268
269 /**
270 * Extends.
271 */
272
273 "extends": function() {
274170 return this.scan(/^extends? +([^\n]+)/, 'extends');
275 },
276
277 /**
278 * Block prepend.
279 */
280
281 prepend: function() {
282170 var captures;
283170 if (captures = /^prepend +([^\n]+)/.exec(this.input)) {
2840 this.consume(captures[0].length);
2850 var mode = 'prepend'
286 , name = captures[1]
287 , tok = this.tok('block', name);
2880 tok.mode = mode;
2890 return tok;
290 }
291 },
292
293 /**
294 * Block append.
295 */
296
297 append: function() {
298170 var captures;
299170 if (captures = /^append +([^\n]+)/.exec(this.input)) {
3000 this.consume(captures[0].length);
3010 var mode = 'append'
302 , name = captures[1]
303 , tok = this.tok('block', name);
3040 tok.mode = mode;
3050 return tok;
306 }
307 },
308
309 /**
310 * Block.
311 */
312
313 block: function() {
314170 var captures;
315170 if (captures = /^block\b *(?:(prepend|append) +)?([^\n]*)/.exec(this.input)) {
3160 this.consume(captures[0].length);
3170 var mode = captures[1] || 'replace'
318 , name = captures[2]
319 , tok = this.tok('block', name);
320
3210 tok.mode = mode;
3220 return tok;
323 }
324 },
325
326 /**
327 * Yield.
328 */
329
330 yield: function() {
331171 return this.scan(/^yield */, 'yield');
332 },
333
334 /**
335 * Include.
336 */
337
338 include: function() {
339170 return this.scan(/^include +([^\n]+)/, 'include');
340 },
341
342 /**
343 * Case.
344 */
345
346 "case": function() {
347170 return this.scan(/^case +([^\n]+)/, 'case');
348 },
349
350 /**
351 * When.
352 */
353
354 when: function() {
355170 return this.scan(/^when +([^:\n]+)/, 'when');
356 },
357
358 /**
359 * Default.
360 */
361
362 "default": function() {
363170 return this.scan(/^default */, 'default');
364 },
365
366 /**
367 * Assignment.
368 */
369
370 assignment: function() {
371160 var captures;
372160 if (captures = /^(\w+) += *([^;\n]+)( *;? *)/.exec(this.input)) {
3732 this.consume(captures[0].length);
3742 var name = captures[1]
375 , val = captures[2];
3762 return this.tok('code', 'var ' + name + ' = (' + val + ');');
377 }
378 },
379
380 /**
381 * Call mixin.
382 */
383
384 call: function(){
385167 var captures;
386167 if (captures = /^\+([-\w]+)/.exec(this.input)) {
3870 this.consume(captures[0].length);
3880 var tok = this.tok('call', captures[1]);
389
390 // Check for args (not attributes)
3910 if (captures = /^ *\((.*?)\)/.exec(this.input)) {
3920 if (!/^ *[-\w]+ *=/.test(captures[1])) {
3930 this.consume(captures[0].length);
3940 tok.args = captures[1];
395 }
396 }
397
3980 return tok;
399 }
400 },
401
402 /**
403 * Mixin.
404 */
405
406 mixin: function(){
407167 var captures;
408167 if (captures = /^mixin +([-\w]+)(?: *\((.*)\))?/.exec(this.input)) {
4090 this.consume(captures[0].length);
4100 var tok = this.tok('mixin', captures[1]);
4110 tok.args = captures[2];
4120 return tok;
413 }
414 },
415
416 /**
417 * Conditional.
418 */
419
420 conditional: function() {
421167 var captures;
422167 if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) {
4234 this.consume(captures[0].length);
4244 var type = captures[1]
425 , js = captures[2];
426
4274 switch (type) {
4284 case 'if': js = 'if (' + js + ')'; break;
4290 case 'unless': js = 'if (!(' + js + '))'; break;
4302 case 'else if': js = 'else if (' + js + ')'; break;
4312 case 'else': js = 'else'; break;
432 }
433
4344 return this.tok('code', js);
435 }
436 },
437
438 /**
439 * While.
440 */
441
442 "while": function() {
443160 var captures;
444160 if (captures = /^while +([^\n]+)/.exec(this.input)) {
4450 this.consume(captures[0].length);
4460 return this.tok('code', 'while (' + captures[1] + ')');
447 }
448 },
449
450 /**
451 * Each.
452 */
453
454 each: function() {
455163 var captures;
456163 if (captures = /^(?:- *)?(?:each|for) +(\w+)(?: *, *(\w+))? * in *([^\n]+)/.exec(this.input)) {
4573 this.consume(captures[0].length);
4583 var tok = this.tok('each', captures[1]);
4593 tok.key = captures[2] || '$index';
4603 tok.code = captures[3];
4613 return tok;
462 }
463 },
464
465 /**
466 * Code.
467 */
468
469 code: function() {
470125 var captures;
471125 if (captures = /^(!?=|-)([^\n]+)/.exec(this.input)) {
47216 this.consume(captures[0].length);
47316 var flags = captures[1];
47416 captures[1] = captures[2];
47516 var tok = this.tok('code', captures[1]);
47616 tok.escape = flags[0] === '=';
47716 tok.buffer = flags[0] === '=' || flags[1] === '=';
47816 return tok;
479 }
480 },
481
482 /**
483 * Attributes.
484 */
485
486 attrs: function() {
48778 if ('(' == this.input.charAt(0)) {
4887 var index = this.indexOfDelimiters('(', ')')
489 , str = this.input.substr(1, index-1)
490 , tok = this.tok('attrs')
491 , len = str.length
492 , colons = this.colons
493 , states = ['key']
494 , escapedAttr
495 , key = ''
496 , val = ''
497 , quote
498 , c
499 , p;
500
5017 function state(){
502206 return states[states.length - 1];
503 }
504
5057 function interpolate(attr) {
5067 return attr.replace(/#\{([^}]+)\}/g, function(_, expr){
5071 return quote + " + (" + expr + ") + " + quote;
508 });
509 }
510
5117 this.consume(index + 1);
5127 tok.attrs = {};
5137 tok.escaped = {};
514
5157 function parse(c) {
516206 var real = c;
517 // TODO: remove when people fix ":"
518206 if (colons && ':' == c) c = '=';
519206 switch (c) {
520 case ',':
521 case '\n':
5227 switch (state()) {
523 case 'expr':
524 case 'array':
525 case 'string':
526 case 'object':
5270 val += c;
5280 break;
529 default:
5307 states.push('key');
5317 val = val.trim();
5327 key = key.trim();
5337 if ('' == key) return;
5347 key = key.replace(/^['"]|['"]$/g, '').replace('!', '');
5357 tok.escaped[key] = escapedAttr;
5367 tok.attrs[key] = '' == val
537 ? true
538 : interpolate(val);
5397 key = val = '';
540 }
5417 break;
542 case '=':
5437 switch (state()) {
544 case 'key char':
5450 key += real;
5460 break;
547 case 'val':
548 case 'expr':
549 case 'array':
550 case 'string':
551 case 'object':
5520 val += real;
5530 break;
554 default:
5557 escapedAttr = '!' != p;
5567 states.push('val');
557 }
5587 break;
559 case '(':
5603 if ('val' == state()
5613 || 'expr' == state()) states.push('expr');
5623 val += c;
5633 break;
564 case ')':
5653 if ('expr' == state()
5663 || 'val' == state()) states.pop();
5673 val += c;
5683 break;
569 case '{':
5701 if ('val' == state()) states.push('object');
5711 val += c;
5721 break;
573 case '}':
5741 if ('object' == state()) states.pop();
5751 val += c;
5761 break;
577 case '[':
5780 if ('val' == state()) states.push('array');
5790 val += c;
5800 break;
581 case ']':
5820 if ('array' == state()) states.pop();
5830 val += c;
5840 break;
585 case '"':
586 case "'":
5876 switch (state()) {
588 case 'key':
5890 states.push('key char');
5900 break;
591 case 'key char':
5920 states.pop();
5930 break;
594 case 'string':
5956 if (c == quote) states.pop();
5963 val += c;
5973 break;
598 default:
5993 states.push('string');
6003 val += c;
6013 quote = c;
602 }
6036 break;
604 case '':
6050 break;
606 default:
607178 switch (state()) {
608 case 'key':
609 case 'key char':
61029 key += c;
61129 break;
612 default:
613149 val += c;
614 }
615 }
616206 p = c;
617 }
618
6197 for (var i = 0; i < len; ++i) {
620199 parse(str.charAt(i));
621 }
622
6237 parse(',');
624
6257 if ('/' == this.input.charAt(0)) {
6260 this.consume(1);
6270 tok.selfClosing = true;
628 }
629
6307 return tok;
631 }
632 },
633
634 /**
635 * Indent | Outdent | Newline.
636 */
637
638 indent: function() {
63971 var captures, re;
640
641 // established regexp
64271 if (this.indentRe) {
64368 captures = this.indentRe.exec(this.input);
644 // determine regexp
645 } else {
646 // tabs
6473 re = /^\n(\t*) */;
6483 captures = re.exec(this.input);
649
650 // spaces
6513 if (captures && !captures[1].length) {
6523 re = /^\n( *)/;
6533 captures = re.exec(this.input);
654 }
655
656 // established
6575 if (captures && captures[1].length) this.indentRe = re;
658 }
659
66071 if (captures) {
66160 var tok
662 , indents = captures[1].length;
663
66460 ++this.lineno;
66560 this.consume(indents + 1);
666
66760 if (' ' == this.input[0] || '\t' == this.input[0]) {
6680 throw new Error('Invalid indentation, you can use tabs or spaces but not both');
669 }
670
671 // blank line
67260 if ('\n' == this.input[0]) return this.tok('newline');
673
674 // outdent
67560 if (this.indentStack.length && indents < this.indentStack[0]) {
67611 while (this.indentStack.length && this.indentStack[0] > indents) {
67726 this.stash.push(this.tok('outdent'));
67826 this.indentStack.shift();
679 }
68011 tok = this.stash.pop();
681 // indent
68249 } else if (indents && indents != this.indentStack[0]) {
68326 this.indentStack.unshift(indents);
68426 tok = this.tok('indent', indents);
685 // newline
686 } else {
68723 tok = this.tok('newline');
688 }
689
69060 return tok;
691 }
692 },
693
694 /**
695 * Pipe-less text consumed only when
696 * pipeless is true;
697 */
698
699 pipelessText: function() {
700171 if (this.pipeless) {
7010 if ('\n' == this.input[0]) return;
7020 var i = this.input.indexOf('\n');
7030 if (-1 == i) i = this.input.length;
7040 var str = this.input.substr(0, i);
7050 this.consume(str.length);
7060 return this.tok('text', str);
707 }
708 },
709
710 /**
711 * ':'
712 */
713
714 colon: function() {
71511 return this.scan(/^: */, ':');
716 },
717
718 /**
719 * Return the next token object, or those
720 * previously stashed by lookahead.
721 *
722 * @return {Object}
723 * @api private
724 */
725
726 advance: function(){
727214 return this.stashed()
728 || this.next();
729 },
730
731 /**
732 * Return the next token object.
733 *
734 * @return {Object}
735 * @api private
736 */
737
738 next: function() {
739204 return this.deferred()
740 || this.blank()
741 || this.eos()
742 || this.pipelessText()
743 || this.yield()
744 || this.doctype()
745 || this.interpolation()
746 || this["case"]()
747 || this.when()
748 || this["default"]()
749 || this["extends"]()
750 || this.append()
751 || this.prepend()
752 || this.block()
753 || this.include()
754 || this.mixin()
755 || this.call()
756 || this.conditional()
757 || this.each()
758 || this["while"]()
759 || this.assignment()
760 || this.tag()
761 || this.filter()
762 || this.code()
763 || this.id()
764 || this.className()
765 || this.attrs()
766 || this.indent()
767 || this.comment()
768 || this.colon()
769 || this.text();
770 }
771};
772

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/attrs.js

53%
15
8
7
LineHitsSource
1
2/*!
3 * Jade - nodes - Attrs
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node'),
13 Block = require('./block');
14
15/**
16 * Initialize a `Attrs` node.
17 *
18 * @api public
19 */
20
211var Attrs = module.exports = function Attrs() {
220 this.attrs = [];
23};
24
25/**
26 * Inherit from `Node`.
27 */
28
291Attrs.prototype.__proto__ = Node.prototype;
30
31/**
32 * Set attribute `name` to `val`, keep in mind these become
33 * part of a raw js object literal, so to quote a value you must
34 * '"quote me"', otherwise or example 'user.name' is literal JavaScript.
35 *
36 * @param {String} name
37 * @param {String} val
38 * @param {Boolean} escaped
39 * @return {Tag} for chaining
40 * @api public
41 */
42
431Attrs.prototype.setAttribute = function(name, val, escaped){
4438 this.attrs.push({ name: name, val: val, escaped: escaped });
4538 return this;
46};
47
48/**
49 * Remove attribute `name` when present.
50 *
51 * @param {String} name
52 * @api public
53 */
54
551Attrs.prototype.removeAttribute = function(name){
560 for (var i = 0, len = this.attrs.length; i < len; ++i) {
570 if (this.attrs[i] && this.attrs[i].name == name) {
580 delete this.attrs[i];
59 }
60 }
61};
62
63/**
64 * Get attribute value by `name`.
65 *
66 * @param {String} name
67 * @return {String}
68 * @api public
69 */
70
711Attrs.prototype.getAttribute = function(name){
720 for (var i = 0, len = this.attrs.length; i < len; ++i) {
730 if (this.attrs[i] && this.attrs[i].name == name) {
740 return this.attrs[i].val;
75 }
76 }
77};
78

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/block-comment.js

50%
6
3
3
LineHitsSource
1
2/*!
3 * Jade - nodes - BlockComment
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node');
13
14/**
15 * Initialize a `BlockComment` with the given `block`.
16 *
17 * @param {String} val
18 * @param {Block} block
19 * @param {Boolean} buffer
20 * @api public
21 */
22
231var BlockComment = module.exports = function BlockComment(val, block, buffer) {
240 this.block = block;
250 this.val = val;
260 this.buffer = buffer;
27};
28
29/**
30 * Inherit from `Node`.
31 */
32
331BlockComment.prototype.__proto__ = Node.prototype;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/block.js

46%
28
13
15
LineHitsSource
1
2/*!
3 * Jade - nodes - Block
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node');
13
14/**
15 * Initialize a new `Block` with an optional `node`.
16 *
17 * @param {Node} node
18 * @api public
19 */
20
211var Block = module.exports = function Block(node){
2275 this.nodes = [];
2375 if (node) this.push(node);
24};
25
26/**
27 * Inherit from `Node`.
28 */
29
301Block.prototype.__proto__ = Node.prototype;
31
32/**
33 * Block flag.
34 */
35
361Block.prototype.isBlock = true;
37
38/**
39 * Replace the nodes in `other` with the nodes
40 * in `this` block.
41 *
42 * @param {Block} other
43 * @api private
44 */
45
461Block.prototype.replace = function(other){
470 other.nodes = this.nodes;
48};
49
50/**
51 * Pust the given `node`.
52 *
53 * @param {Node} node
54 * @return {Number}
55 * @api public
56 */
57
581Block.prototype.push = function(node){
59119 return this.nodes.push(node);
60};
61
62/**
63 * Check if this block is empty.
64 *
65 * @return {Boolean}
66 * @api public
67 */
68
691Block.prototype.isEmpty = function(){
700 return 0 == this.nodes.length;
71};
72
73/**
74 * Unshift the given `node`.
75 *
76 * @param {Node} node
77 * @return {Number}
78 * @api public
79 */
80
811Block.prototype.unshift = function(node){
820 return this.nodes.unshift(node);
83};
84
85/**
86 * Return the "last" block, or the first `yield` node.
87 *
88 * @return {Block}
89 * @api private
90 */
91
921Block.prototype.includeBlock = function(){
930 var ret = this
94 , node;
95
960 for (var i = 0, len = this.nodes.length; i < len; ++i) {
970 node = this.nodes[i];
980 if (node.yield) return node;
990 else if (node.textOnly) continue;
1000 else if (node.includeBlock) ret = node.includeBlock();
1010 else if (node.block && !node.block.isEmpty()) ret = node.block.includeBlock();
102 }
103
1040 return ret;
105};
106
107/**
108 * Return a clone of this block.
109 *
110 * @return {Block}
111 * @api private
112 */
113
1141Block.prototype.clone = function(){
1150 var clone = new Block;
1160 for (var i = 0, len = this.nodes.length; i < len; ++i) {
1170 clone.push(this.nodes[i].clone());
118 }
1190 return clone;
120};
121
122

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/case.js

50%
10
5
5
LineHitsSource
1
2/*!
3 * Jade - nodes - Case
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node');
13
14/**
15 * Initialize a new `Case` with `expr`.
16 *
17 * @param {String} expr
18 * @api public
19 */
20
211var Case = exports = module.exports = function Case(expr, block){
220 this.expr = expr;
230 this.block = block;
24};
25
26/**
27 * Inherit from `Node`.
28 */
29
301Case.prototype.__proto__ = Node.prototype;
31
321var When = exports.When = function When(expr, block){
330 this.expr = expr;
340 this.block = block;
350 this.debug = false;
36};
37
38/**
39 * Inherit from `Node`.
40 */
41
421When.prototype.__proto__ = Node.prototype;
43
44

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/code.js

100%
7
7
0
LineHitsSource
1
2/*!
3 * Jade - nodes - Code
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node');
13
14/**
15 * Initialize a `Code` node with the given code `val`.
16 * Code may also be optionally buffered and escaped.
17 *
18 * @param {String} val
19 * @param {Boolean} buffer
20 * @param {Boolean} escape
21 * @api public
22 */
23
241var Code = module.exports = function Code(val, buffer, escape) {
2522 this.val = val;
2622 this.buffer = buffer;
2722 this.escape = escape;
2824 if (val.match(/^ *else/)) this.debug = false;
29};
30
31/**
32 * Inherit from `Node`.
33 */
34
351Code.prototype.__proto__ = Node.prototype;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/comment.js

60%
5
3
2
LineHitsSource
1
2/*!
3 * Jade - nodes - Comment
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node');
13
14/**
15 * Initialize a `Comment` with the given `val`, optionally `buffer`,
16 * otherwise the comment may render in the output.
17 *
18 * @param {String} val
19 * @param {Boolean} buffer
20 * @api public
21 */
22
231var Comment = module.exports = function Comment(val, buffer) {
240 this.val = val;
250 this.buffer = buffer;
26};
27
28/**
29 * Inherit from `Node`.
30 */
31
321Comment.prototype.__proto__ = Node.prototype;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/doctype.js

100%
4
4
0
LineHitsSource
1
2/*!
3 * Jade - nodes - Doctype
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node');
13
14/**
15 * Initialize a `Doctype` with the given `val`.
16 *
17 * @param {String} val
18 * @api public
19 */
20
211var Doctype = module.exports = function Doctype(val) {
221 this.val = val;
23};
24
25/**
26 * Inherit from `Node`.
27 */
28
291Doctype.prototype.__proto__ = Node.prototype;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/each.js

100%
7
7
0
LineHitsSource
1
2/*!
3 * Jade - nodes - Each
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node');
13
14/**
15 * Initialize an `Each` node, representing iteration
16 *
17 * @param {String} obj
18 * @param {String} val
19 * @param {String} key
20 * @param {Block} block
21 * @api public
22 */
23
241var Each = module.exports = function Each(obj, val, key, block) {
253 this.obj = obj;
263 this.val = val;
273 this.key = key;
283 this.block = block;
29};
30
31/**
32 * Inherit from `Node`.
33 */
34
351Each.prototype.__proto__ = Node.prototype;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/filter.js

42%
7
3
4
LineHitsSource
1
2/*!
3 * Jade - nodes - Filter
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node')
13 , Block = require('./block');
14
15/**
16 * Initialize a `Filter` node with the given
17 * filter `name` and `block`.
18 *
19 * @param {String} name
20 * @param {Block|Node} block
21 * @api public
22 */
23
241var Filter = module.exports = function Filter(name, block, attrs) {
250 this.name = name;
260 this.block = block;
270 this.attrs = attrs;
280 this.isASTFilter = !block.nodes.every(function(node){ return node.isText });
29};
30
31/**
32 * Inherit from `Node`.
33 */
34
351Filter.prototype.__proto__ = Node.prototype;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/index.js

100%
13
13
0
LineHitsSource
1
2/*!
3 * Jade - nodes
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
81exports.Node = require('./node');
91exports.Tag = require('./tag');
101exports.Code = require('./code');
111exports.Each = require('./each');
121exports.Case = require('./case');
131exports.Text = require('./text');
141exports.Block = require('./block');
151exports.Mixin = require('./mixin');
161exports.Filter = require('./filter');
171exports.Comment = require('./comment');
181exports.Literal = require('./literal');
191exports.BlockComment = require('./block-comment');
201exports.Doctype = require('./doctype');
21

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/literal.js

100%
4
4
0
LineHitsSource
1
2/*!
3 * Jade - nodes - Literal
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node');
13
14/**
15 * Initialize a `Literal` node with the given `str.
16 *
17 * @param {String} str
18 * @api public
19 */
20
211var Literal = module.exports = function Literal(str) {
222 this.str = str
23 .replace(/\\/g, "\\\\")
24 .replace(/\n|\r\n/g, "\\n")
25 .replace(/'/g, "\\'");
26};
27
28/**
29 * Inherit from `Node`.
30 */
31
321Literal.prototype.__proto__ = Node.prototype;
33

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/mixin.js

37%
8
3
5
LineHitsSource
1
2/*!
3 * Jade - nodes - Mixin
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Attrs = require('./attrs');
13
14/**
15 * Initialize a new `Mixin` with `name` and `block`.
16 *
17 * @param {String} name
18 * @param {String} args
19 * @param {Block} block
20 * @api public
21 */
22
231var Mixin = module.exports = function Mixin(name, args, block, call){
240 this.name = name;
250 this.args = args;
260 this.block = block;
270 this.attrs = [];
280 this.call = call;
29};
30
31/**
32 * Inherit from `Attrs`.
33 */
34
351Mixin.prototype.__proto__ = Attrs.prototype;
36
37

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/node.js

66%
3
2
1
LineHitsSource
1
2/*!
3 * Jade - nodes - Node
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Initialize a `Node`.
10 *
11 * @api public
12 */
13
141var Node = module.exports = function Node(){};
15
16/**
17 * Clone this node (return itself)
18 *
19 * @return {Node}
20 * @api private
21 */
22
231Node.prototype.clone = function(){
240 return this;
25};
26

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/tag.js

33%
27
9
18
LineHitsSource
1
2/*!
3 * Jade - nodes - Tag
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Attrs = require('./attrs'),
13 Block = require('./block'),
14 inlineTags = require('../inline-tags');
15
16/**
17 * Initialize a `Tag` node with the given tag `name` and optional `block`.
18 *
19 * @param {String} name
20 * @param {Block} block
21 * @api public
22 */
23
241var Tag = module.exports = function Tag(name, block) {
2547 this.name = name;
2647 this.attrs = [];
2747 this.block = block || new Block;
28};
29
30/**
31 * Inherit from `Attrs`.
32 */
33
341Tag.prototype.__proto__ = Attrs.prototype;
35
36/**
37 * Clone this tag.
38 *
39 * @return {Tag}
40 * @api private
41 */
42
431Tag.prototype.clone = function(){
440 var clone = new Tag(this.name, this.block.clone());
450 clone.line = this.line;
460 clone.attrs = this.attrs;
470 clone.textOnly = this.textOnly;
480 return clone;
49};
50
51/**
52 * Check if this tag is an inline tag.
53 *
54 * @return {Boolean}
55 * @api private
56 */
57
581Tag.prototype.isInline = function(){
590 return ~inlineTags.indexOf(this.name);
60};
61
62/**
63 * Check if this tag's contents can be inlined. Used for pretty printing.
64 *
65 * @return {Boolean}
66 * @api private
67 */
68
691Tag.prototype.canInline = function(){
700 var nodes = this.block.nodes;
71
720 function isInline(node){
73 // Recurse if the node is a block
740 if (node.isBlock) return node.nodes.every(isInline);
750 return node.isText || (node.isInline && node.isInline());
76 }
77
78 // Empty tag
790 if (!nodes.length) return true;
80
81 // Text-only or inline-only tag
820 if (1 == nodes.length) return isInline(nodes[0]);
83
84 // Multi-line inline-only tag
850 if (this.block.nodes.every(isInline)) {
860 for (var i = 1, len = nodes.length; i < len; ++i) {
870 if (nodes[i-1].isText && nodes[i].isText)
880 return false;
89 }
900 return true;
91 }
92
93 // Mixed tag
940 return false;
95};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/nodes/text.js

100%
6
6
0
LineHitsSource
1
2/*!
3 * Jade - nodes - Text
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Node = require('./node');
13
14/**
15 * Initialize a `Text` node with optional `line`.
16 *
17 * @param {String} line
18 * @api public
19 */
20
211var Text = module.exports = function Text(line) {
2211 this.val = '';
2322 if ('string' == typeof line) this.val = line;
24};
25
26/**
27 * Inherit from `Node`.
28 */
29
301Text.prototype.__proto__ = Node.prototype;
31
32/**
33 * Flag as text.
34 */
35
361Text.prototype.isText = true;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/parser.js

48%
245
118
127
LineHitsSource
1
2/*!
3 * Jade - Parser
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Module dependencies.
10 */
11
121var Lexer = require('./lexer')
13 , nodes = require('./nodes');
14
15/**
16 * Initialize `Parser` with the given input `str` and `filename`.
17 *
18 * @param {String} str
19 * @param {String} filename
20 * @param {Object} options
21 * @api public
22 */
23
241var Parser = exports = module.exports = function Parser(str, filename, options){
252 this.input = str;
262 this.lexer = new Lexer(str, options);
272 this.filename = filename;
282 this.blocks = {};
292 this.mixins = {};
302 this.options = options;
312 this.contexts = [this];
32};
33
34/**
35 * Tags that may not contain tags.
36 */
37
381var textOnly = exports.textOnly = ['script', 'style'];
39
40/**
41 * Parser prototype.
42 */
43
441Parser.prototype = {
45
46 /**
47 * Push `parser` onto the context stack,
48 * or pop and return a `Parser`.
49 */
50
51 context: function(parser){
522 if (parser) {
531 this.contexts.push(parser);
54 } else {
551 return this.contexts.pop();
56 }
57 },
58
59 /**
60 * Return the next token object.
61 *
62 * @return {Object}
63 * @api private
64 */
65
66 advance: function(){
67214 return this.lexer.advance();
68 },
69
70 /**
71 * Skip `n` tokens.
72 *
73 * @param {Number} n
74 * @api private
75 */
76
77 skip: function(n){
784 while (n--) this.advance();
79 },
80
81 /**
82 * Single token lookahead.
83 *
84 * @return {Object}
85 * @api private
86 */
87
88 peek: function() {
89616 return this.lookahead(1);
90 },
91
92 /**
93 * Return lexer lineno.
94 *
95 * @return {Number}
96 * @api private
97 */
98
99 line: function() {
100112 return this.lexer.lineno;
101 },
102
103 /**
104 * `n` token lookahead.
105 *
106 * @param {Number} n
107 * @return {Object}
108 * @api private
109 */
110
111 lookahead: function(n){
112798 return this.lexer.lookahead(n);
113 },
114
115 /**
116 * Parse input returning a string of js for evaluation.
117 *
118 * @return {String}
119 * @api public
120 */
121
122 parse: function(){
1232 var block = new nodes.Block, parser;
1242 block.line = this.line();
125
1262 while ('eos' != this.peek().type) {
1274 if ('newline' == this.peek().type) {
1281 this.advance();
129 } else {
1303 block.push(this.parseExpr());
131 }
132 }
133
1342 if (parser = this.extending) {
1350 this.context(parser);
1360 var ast = parser.parse();
1370 this.context();
138 // hoist mixins
1390 for (var name in this.mixins)
1400 ast.unshift(this.mixins[name]);
1410 return ast;
142 }
143
1442 return block;
145 },
146
147 /**
148 * Expect the given type, or throw an exception.
149 *
150 * @param {String} type
151 * @api private
152 */
153
154 expect: function(type){
15592 if (this.peek().type === type) {
15692 return this.advance();
157 } else {
1580 throw new Error('expected "' + type + '", but got "' + this.peek().type + '"');
159 }
160 },
161
162 /**
163 * Accept the given `type`.
164 *
165 * @param {String} type
166 * @api private
167 */
168
169 accept: function(type){
1700 if (this.peek().type === type) {
1710 return this.advance();
172 }
173 },
174
175 /**
176 * tag
177 * | doctype
178 * | mixin
179 * | include
180 * | filter
181 * | comment
182 * | text
183 * | each
184 * | code
185 * | yield
186 * | id
187 * | class
188 * | interpolation
189 */
190
191 parseExpr: function(){
19274 switch (this.peek().type) {
193 case 'tag':
19447 return this.parseTag();
195 case 'mixin':
1960 return this.parseMixin();
197 case 'block':
1980 return this.parseBlock();
199 case 'case':
2000 return this.parseCase();
201 case 'when':
2020 return this.parseWhen();
203 case 'default':
2040 return this.parseDefault();
205 case 'extends':
2060 return this.parseExtends();
207 case 'include':
2083 return this.parseInclude();
209 case 'doctype':
2101 return this.parseDoctype();
211 case 'filter':
2120 return this.parseFilter();
213 case 'comment':
2140 return this.parseComment();
215 case 'text':
2160 return this.parseText();
217 case 'each':
2183 return this.parseEach();
219 case 'code':
2206 return this.parseCode();
221 case 'call':
2220 return this.parseCall();
223 case 'interpolation':
2240 return this.parseInterpolation();
225 case 'yield':
2260 this.advance();
2270 var block = new nodes.Block;
2280 block.yield = true;
2290 return block;
230 case 'id':
231 case 'class':
23214 var tok = this.advance();
23314 this.lexer.defer(this.lexer.tok('tag', 'div'));
23414 this.lexer.defer(tok);
23514 return this.parseExpr();
236 default:
2370 throw new Error('unexpected token "' + this.peek().type + '"');
238 }
239 },
240
241 /**
242 * Text
243 */
244
245 parseText: function(){
24611 var tok = this.expect('text')
247 , node = new nodes.Text(tok.val);
24811 node.line = this.line();
24911 return node;
250 },
251
252 /**
253 * ':' expr
254 * | block
255 */
256
257 parseBlockExpansion: function(){
2580 if (':' == this.peek().type) {
2590 this.advance();
2600 return new nodes.Block(this.parseExpr());
261 } else {
2620 return this.block();
263 }
264 },
265
266 /**
267 * case
268 */
269
270 parseCase: function(){
2710 var val = this.expect('case').val
272 , node = new nodes.Case(val);
2730 node.line = this.line();
2740 node.block = this.block();
2750 return node;
276 },
277
278 /**
279 * when
280 */
281
282 parseWhen: function(){
2830 var val = this.expect('when').val
2840 return new nodes.Case.When(val, this.parseBlockExpansion());
285 },
286
287 /**
288 * default
289 */
290
291 parseDefault: function(){
2920 this.expect('default');
2930 return new nodes.Case.When('default', this.parseBlockExpansion());
294 },
295
296 /**
297 * code
298 */
299
300 parseCode: function(){
30122 var tok = this.expect('code')
302 , node = new nodes.Code(tok.val, tok.buffer, tok.escape)
303 , block
304 , i = 1;
30522 node.line = this.line();
30633 while (this.lookahead(i) && 'newline' == this.lookahead(i).type) ++i;
30722 block = 'indent' == this.lookahead(i).type;
30822 if (block) {
3094 this.skip(i-1);
3104 node.block = this.block();
311 }
31222 return node;
313 },
314
315 /**
316 * comment
317 */
318
319 parseComment: function(){
3200 var tok = this.expect('comment')
321 , node;
322
3230 if ('indent' == this.peek().type) {
3240 node = new nodes.BlockComment(tok.val, this.block(), tok.buffer);
325 } else {
3260 node = new nodes.Comment(tok.val, tok.buffer);
327 }
328
3290 node.line = this.line();
3300 return node;
331 },
332
333 /**
334 * doctype
335 */
336
337 parseDoctype: function(){
3381 var tok = this.expect('doctype')
339 , node = new nodes.Doctype(tok.val);
3401 node.line = this.line();
3411 return node;
342 },
343
344 /**
345 * filter attrs? text-block
346 */
347
348 parseFilter: function(){
3490 var block
350 , tok = this.expect('filter')
351 , attrs = this.accept('attrs');
352
3530 this.lexer.pipeless = true;
3540 block = this.parseTextBlock();
3550 this.lexer.pipeless = false;
356
3570 var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs);
3580 node.line = this.line();
3590 return node;
360 },
361
362 /**
363 * tag ':' attrs? block
364 */
365
366 parseASTFilter: function(){
3670 var block
368 , tok = this.expect('tag')
369 , attrs = this.accept('attrs');
370
3710 this.expect(':');
3720 block = this.block();
373
3740 var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs);
3750 node.line = this.line();
3760 return node;
377 },
378
379 /**
380 * each block
381 */
382
383 parseEach: function(){
3843 var tok = this.expect('each')
385 , node = new nodes.Each(tok.code, tok.val, tok.key);
3863 node.line = this.line();
3873 node.block = this.block();
3883 return node;
389 },
390
391 /**
392 * 'extends' name
393 */
394
395 parseExtends: function(){
3960 var path = require('path')
397 , fs = require('fs')
398 , dirname = path.dirname
399 , basename = path.basename
400 , join = path.join;
401
4020 if (!this.filename)
4030 throw new Error('the "filename" option is required to extend templates');
404
4050 var path = this.expect('extends').val.trim()
406 , dir = dirname(this.filename);
407
4080 var path = join(dir, path + '.jade')
409 , str = fs.readFileSync(path, 'utf8')
410 , parser = new Parser(str, path, this.options);
411
4120 parser.blocks = this.blocks;
4130 parser.contexts = this.contexts;
4140 this.extending = parser;
415
416 // TODO: null node
4170 return new nodes.Literal('');
418 },
419
420 /**
421 * 'block' name block
422 */
423
424 parseBlock: function(){
4250 var block = this.expect('block')
426 , mode = block.mode
427 , name = block.val.trim();
428
4290 block = 'indent' == this.peek().type
430 ? this.block()
431 : new nodes.Block(new nodes.Literal(''));
432
4330 var prev = this.blocks[name];
434
4350 if (prev) {
4360 switch (prev.mode) {
437 case 'append':
4380 block.nodes = block.nodes.concat(prev.nodes);
4390 prev = block;
4400 break;
441 case 'prepend':
4420 block.nodes = prev.nodes.concat(block.nodes);
4430 prev = block;
4440 break;
445 }
446 }
447
4480 block.mode = mode;
4490 return this.blocks[name] = prev || block;
450 },
451
452 /**
453 * include block?
454 */
455
456 parseInclude: function(){
4573 var path = require('path')
458 , fs = require('fs')
459 , dirname = path.dirname
460 , basename = path.basename
461 , join = path.join;
462
4633 var path = this.expect('include').val.trim()
464 , dir = dirname(this.filename);
465
4663 if (!this.filename)
4670 throw new Error('the "filename" option is required to use includes');
468
469 // no extension
4703 if (!~basename(path).indexOf('.')) {
4711 path += '.jade';
472 }
473
474 // non-jade
4753 if ('.jade' != path.substr(-5)) {
4762 var path = join(dir, path)
477 , str = fs.readFileSync(path, 'utf8');
4782 return new nodes.Literal(str);
479 }
480
4811 var path = join(dir, path)
482 , str = fs.readFileSync(path, 'utf8')
483 , parser = new Parser(str, path, this.options);
4841 parser.blocks = this.blocks;
4851 parser.mixins = this.mixins;
486
4871 this.context(parser);
4881 var ast = parser.parse();
4891 this.context();
4901 ast.filename = path;
491
4921 if ('indent' == this.peek().type) {
4930 ast.includeBlock().push(this.block());
494 }
495
4961 return ast;
497 },
498
499 /**
500 * call ident block
501 */
502
503 parseCall: function(){
5040 var tok = this.expect('call')
505 , name = tok.val
506 , args = tok.args
507 , mixin = new nodes.Mixin(name, args, new nodes.Block, true);
508
5090 this.tag(mixin);
5100 if (mixin.block.isEmpty()) mixin.block = null;
5110 return mixin;
512 },
513
514 /**
515 * mixin block
516 */
517
518 parseMixin: function(){
5190 var tok = this.expect('mixin')
520 , name = tok.val
521 , args = tok.args
522 , mixin;
523
524 // definition
5250 if ('indent' == this.peek().type) {
5260 mixin = new nodes.Mixin(name, args, this.block(), false);
5270 this.mixins[name] = mixin;
5280 return mixin;
529 // call
530 } else {
5310 return new nodes.Mixin(name, args, null, true);
532 }
533 },
534
535 /**
536 * indent (text | newline)* outdent
537 */
538
539 parseTextBlock: function(){
5400 var block = new nodes.Block;
5410 block.line = this.line();
5420 var spaces = this.expect('indent').val;
5430 if (null == this._spaces) this._spaces = spaces;
5440 var indent = Array(spaces - this._spaces + 1).join(' ');
5450 while ('outdent' != this.peek().type) {
5460 switch (this.peek().type) {
547 case 'newline':
5480 this.advance();
5490 break;
550 case 'indent':
5510 this.parseTextBlock().nodes.forEach(function(node){
5520 block.push(node);
553 });
5540 break;
555 default:
5560 var text = new nodes.Text(indent + this.advance().val);
5570 text.line = this.line();
5580 block.push(text);
559 }
560 }
561
5620 if (spaces == this._spaces) this._spaces = null;
5630 this.expect('outdent');
5640 return block;
565 },
566
567 /**
568 * indent expr* outdent
569 */
570
571 block: function(){
57226 var block = new nodes.Block;
57326 block.line = this.line();
57426 this.expect('indent');
57526 while ('outdent' != this.peek().type) {
57661 if ('newline' == this.peek().type) {
5774 this.advance();
578 } else {
57957 block.push(this.parseExpr());
580 }
581 }
58226 this.expect('outdent');
58326 return block;
584 },
585
586 /**
587 * interpolation (attrs | class | id)* (text | code | ':')? newline* block?
588 */
589
590 parseInterpolation: function(){
5910 var tok = this.advance();
5920 var tag = new nodes.Tag(tok.val);
5930 tag.buffer = true;
5940 return this.tag(tag);
595 },
596
597 /**
598 * tag (attrs | class | id)* (text | code | ':')? newline* block?
599 */
600
601 parseTag: function(){
602 // ast-filter look-ahead
60347 var i = 2;
60450 if ('attrs' == this.lookahead(i).type) ++i;
60547 if (':' == this.lookahead(i).type) {
6060 if ('indent' == this.lookahead(++i).type) {
6070 return this.parseASTFilter();
608 }
609 }
610
61147 var tok = this.advance()
612 , tag = new nodes.Tag(tok.val);
613
61447 tag.selfClosing = tok.selfClosing;
615
61647 return this.tag(tag);
617 },
618
619 /**
620 * Parse tag.
621 */
622
623 tag: function(tag){
62447 var dot;
625
62647 tag.line = this.line();
627
628 // (attrs | class | id)*
629 out:
630 while (true) {
63185 switch (this.peek().type) {
632 case 'id':
633 case 'class':
63431 var tok = this.advance();
63531 tag.setAttribute(tok.type, "'" + tok.val + "'");
63631 continue;
637 case 'attrs':
6387 var tok = this.advance()
639 , obj = tok.attrs
640 , escaped = tok.escaped
641 , names = Object.keys(obj);
642
6437 if (tok.selfClosing) tag.selfClosing = true;
644
6457 for (var i = 0, len = names.length; i < len; ++i) {
6467 var name = names[i]
647 , val = obj[name];
6487 tag.setAttribute(name, val, escaped[name]);
649 }
6507 continue;
651 default:
65247 break out;
653 }
654 }
655
656 // check immediate '.'
65747 if ('.' == this.peek().val) {
6580 dot = tag.textOnly = true;
6590 this.advance();
660 }
661
662 // (text | code | ':')?
66347 switch (this.peek().type) {
664 case 'text':
66511 tag.block.push(this.parseText());
66611 break;
667 case 'code':
66816 tag.code = this.parseCode();
66916 break;
670 case ':':
6710 this.advance();
6720 tag.block = new nodes.Block;
6730 tag.block.push(this.parseExpr());
6740 break;
675 }
676
677 // newline*
67865 while ('newline' == this.peek().type) this.advance();
679
68047 tag.textOnly = tag.textOnly || ~textOnly.indexOf(tag.name);
681
682 // script special-case
68347 if ('script' == tag.name) {
6840 var type = tag.getAttribute('type');
6850 if (!dot && type && 'text/javascript' != type.replace(/^['"]|['"]$/g, '')) {
6860 tag.textOnly = false;
687 }
688 }
689
690 // block?
69147 if ('indent' == this.peek().type) {
69219 if (tag.textOnly) {
6930 this.lexer.pipeless = true;
6940 tag.block = this.parseTextBlock();
6950 this.lexer.pipeless = false;
696 } else {
69719 var block = this.block();
69819 if (tag.block) {
69919 for (var i = 0, len = block.nodes.length; i < len; ++i) {
70048 tag.block.push(block.nodes[i]);
701 }
702 } else {
7030 tag.block = block;
704 }
705 }
706 }
707
70847 return tag;
709 }
710};
711

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/runtime.js

38%
57
22
35
LineHitsSource
1
2/*!
3 * Jade - runtime
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Lame Array.isArray() polyfill for now.
10 */
11
121if (!Array.isArray) {
130 Array.isArray = function(arr){
140 return '[object Array]' == Object.prototype.toString.call(arr);
15 };
16}
17
18/**
19 * Lame Object.keys() polyfill for now.
20 */
21
221if (!Object.keys) {
230 Object.keys = function(obj){
240 var arr = [];
250 for (var key in obj) {
260 if (obj.hasOwnProperty(key)) {
270 arr.push(key);
28 }
29 }
300 return arr;
31 }
32}
33
34/**
35 * Merge two attribute objects giving precedence
36 * to values in object `b`. Classes are special-cased
37 * allowing for arrays and merging/joining appropriately
38 * resulting in a string.
39 *
40 * @param {Object} a
41 * @param {Object} b
42 * @return {Object} a
43 * @api private
44 */
45
461exports.merge = function merge(a, b) {
470 var ac = a['class'];
480 var bc = b['class'];
49
500 if (ac || bc) {
510 ac = ac || [];
520 bc = bc || [];
530 if (!Array.isArray(ac)) ac = [ac];
540 if (!Array.isArray(bc)) bc = [bc];
550 ac = ac.filter(nulls);
560 bc = bc.filter(nulls);
570 a['class'] = ac.concat(bc).join(' ');
58 }
59
600 for (var key in b) {
610 if (key != 'class') {
620 a[key] = b[key];
63 }
64 }
65
660 return a;
67};
68
69/**
70 * Filter null `val`s.
71 *
72 * @param {Mixed} val
73 * @return {Mixed}
74 * @api private
75 */
76
771function nulls(val) {
780 return val != null;
79}
80
81/**
82 * Render the given attributes object.
83 *
84 * @param {Object} obj
85 * @param {Object} escaped
86 * @return {String}
87 * @api private
88 */
89
901exports.attrs = function attrs(obj, escaped){
9170 var buf = []
92 , terse = obj.terse;
93
9470 delete obj.terse;
9570 var keys = Object.keys(obj)
96 , len = keys.length;
97
9870 if (len) {
9970 buf.push('');
10070 for (var i = 0; i < len; ++i) {
10171 var key = keys[i]
102 , val = obj[key];
103
10471 if ('boolean' == typeof val || null == val) {
1050 if (val) {
1060 terse
107 ? buf.push(key)
108 : buf.push(key + '="' + key + '"');
109 }
11071 } else if (0 == key.indexOf('data') && 'string' != typeof val) {
1110 buf.push(key + "='" + JSON.stringify(val) + "'");
11271 } else if ('class' == key && Array.isArray(val)) {
1130 buf.push(key + '="' + exports.escape(val.join(' ')) + '"');
11471 } else if (escaped && escaped[key]) {
1152 buf.push(key + '="' + exports.escape(val) + '"');
116 } else {
11769 buf.push(key + '="' + val + '"');
118 }
119 }
120 }
121
12270 return buf.join(' ');
123};
124
125/**
126 * Escape the given string of `html`.
127 *
128 * @param {String} html
129 * @return {String}
130 * @api private
131 */
132
1331exports.escape = function escape(html){
1342 return String(html)
135 .replace(/&(?!(\w+|\#\d+);)/g, '&')
136 .replace(/</g, '<')
137 .replace(/>/g, '>')
138 .replace(/"/g, '"');
139};
140
141/**
142 * Re-throw the given `err` in context to the
143 * the jade in `filename` at the given `lineno`.
144 *
145 * @param {Error} err
146 * @param {String} filename
147 * @param {String} lineno
148 * @api private
149 */
150
1511exports.rethrow = function rethrow(err, filename, lineno){
1520 if (!filename) throw err;
153
1540 var context = 3
155 , str = require('fs').readFileSync(filename, 'utf8')
156 , lines = str.split('\n')
157 , start = Math.max(lineno - context, 0)
158 , end = Math.min(lines.length, lineno + context);
159
160 // Error context
1610 var context = lines.slice(start, end).map(function(line, i){
1620 var curr = i + start + 1;
1630 return (curr == lineno ? ' > ' : ' ')
164 + curr
165 + '| '
166 + line;
167 }).join('\n');
168
169 // Alter exception message
1700 err.path = filename;
1710 err.message = (filename || 'Jade') + ':' + lineno
172 + '\n' + context + '\n\n' + err.message;
1730 throw err;
174};
175

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/self-closing.js

100%
1
1
0
LineHitsSource
1
2/*!
3 * Jade - self closing tags
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
81module.exports = [
9 'meta'
10 , 'img'
11 , 'link'
12 , 'input'
13 , 'source'
14 , 'area'
15 , 'base'
16 , 'col'
17 , 'br'
18 , 'hr'
19];

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mocha/node_modules/jade/lib/utils.js

100%
7
7
0
LineHitsSource
1
2/*!
3 * Jade - utils
4 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5 * MIT Licensed
6 */
7
8/**
9 * Convert interpolation in the given string to JavaScript.
10 *
11 * @param {String} str
12 * @return {String}
13 * @api private
14 */
15
161var interpolate = exports.interpolate = function(str){
1719 return str.replace(/(\\)?([#!]){(.*?)}/g, function(str, escape, flag, code){
185 return escape
19 ? str
20 : "' + "
21 + ('!' == flag ? '' : 'escape')
22 + "((interp = " + code.replace(/\\'/g, "'")
23 + ") == null ? '' : interp) + '";
24 });
25};
26
27/**
28 * Escape single quotes in `str`.
29 *
30 * @param {String} str
31 * @return {String}
32 * @api private
33 */
34
351var escape = exports.escape = function(str) {
3689 return str.replace(/'/g, "\\'");
37};
38
39/**
40 * Interpolate, and escape the given `str`.
41 *
42 * @param {String} str
43 * @return {String}
44 * @api private
45 */
46
471exports.text = function(str){
4819 return interpolate(escape(str));
49};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/Collection.js

9%
115
11
104
LineHitsSource
11'use strict';
2
31var logger = require('./Logger');
41var ObjectId = require('mongodb').BSONPure.ObjectID;
51var _ = require('lodash');
6
71var db = require('./db');
81var utils = require('./utils');
91var filter = require('./options/Options');
101var validation = require('./validation/Validation');
111var operations = require('./operations/Operations');
12
131module.exports = Collection;
141function Collection(mongoCollection, Model) {
150 var name = this.name = mongoCollection.name;
16// var opts = this.opts = mongoCollection.opts;
17// var conn = this.conn = mongoCollection.conn;
18 /*jshint -W064 *///new operator.
190 var schema = Model().schema;
20 /*jshint -W106 *///Camel_Case
210 var indexes = {
22 _id_ : [ [ '_id', 1 ] ]
23 };
240 if (!db[name]) {
250 db[name] = {};
26 }
27
28 //-------------------------------------------------------------------------
29 //
30 // un implemented methods. If you need them why not contribute at
31 // https://github.com/mccormicka/Mockgoose
32 //
33 //-------------------------------------------------------------------------
34
35
360 this.ensureIndex = function (index, options, callback) {
370 logger.info('Ensure Index Called with arguments', arguments);
380 indexes[_.keys(index)[0] + '_1'] = _.pairs(index);
390 logger.info('Created indexes ', indexes);
400 callback(null, indexes);
41 };
42
430 this.getIndexes = function (callback) {
440 return callback(null, indexes);
45 };
46
470 this.mapReduce = function () {
480 throw new Error('Collection#mapReduce unimplemented by mockgoose!');
49 };
50
510 this.save = function () {
52 //Save should not need to be implemented! as insert() should be called instead.
530 throw new Error('Collection#save unimplemented by mockgoose!');
54 };
55
56 //-------------------------------------------------------------------------
57 //
58 // Implemented drive methods.
59 //
60 //-------------------------------------------------------------------------
61
620 this.findAndModify = function (conditions, sort, castedDoc, options, callback) {
630 if (options.remove) {
640 this.remove(conditions, options, callback);
65 } else {
660 options.modify = true;
670 this.update(conditions, castedDoc, options, function (err, results) {
680 callback(err, results[0]);
69 });
70 }
71 };
72
730 this.findOne = function (conditions, options, callback) {
740 this.find(conditions, options, function (err, result) {
750 if (err) {
760 return callback(err);
77 }
780 result.toArray(function (err, results) {
790 callback(err, results[0]);
80 });
81 });
82 };
83
840 this.find = function (conditions, options, callback) {
850 var results;
860 var models = db[name];
870 if (!_.isEmpty(conditions)) {
880 results = utils.findModelQuery(models, conditions);
89 } else {
900 results = utils.objectToArray(utils.cloneItems(models));
91 }
920 results = filter.applyOptions(options, results);
93
940 if (results.name === 'MongoError') {
950 callback(results);
96 } else {
970 var result = {
98 toArray: function (callback) {
990 callback(null, results);
100 }
101 };
1020 callback(null, result);
103 }
104 };
105
1060 this.insert = function (obj, options, callback) {
1070 if (!db[name]) {
1080 db[name] = {};
109 }
1100 validation.validate(name, obj, schema, function(err){
1110 if(err){
1120 return callback(err);
113 }
1140 db[name][obj._id] = obj;
1150 logOptions(options);
1160 callback(null, obj);
117 });
118 };
119
1200 this.update = function (conditions, update, options, callback) {
1210 logOptions(options);
1220 var self = this;
1230 this.find(conditions, options, function (err, results) {
1240 if (err) {
1250 return callback(err);
126 }
1270 results.toArray(function (err, results) {
1280 if (!results.length) {
1290 if (options.upsert) {
130 //Found no items.
1310 self.insert({
132 _id: new ObjectId()
133 }, options, function (err, result) {
1340 if (err) {
1350 return callback(err);
136 }
1370 updateFoundItems(options, [result], update, callback);
138 });
139 } else {
1400 callback(null, options.midify ? [] : 0);
141 }
142 } else {
1430 updateFoundItems(options, results, update, callback);
144 }
145 });
146 });
147 };
148
1490 this.remove = function (conditions, options, callback) {
1500 this.find(conditions, options, function (err, results) {
1510 if (err) {
1520 return callback(err);
153 }
1540 results.toArray(function (err, results) {
1550 if (options.remove) {
156 //If set to remove then only remove one item.
1570 if (results.length) {
1580 results = results[0];
1590 delete db[name][results._id];
160 } else {
1610 results = null;
162 }
163 } else {
1640 _.each(results, function (result) {
1650 delete db[name][result._id];
166 });
167 }
1680 callback(null, results);
169 });
170 });
171 };
172
1730 this.count = function (conditions, options, callback) {
1740 this.find(conditions, options, function (err, results) {
1750 if (err) {
1760 return callback(err);
177 }
1780 results.toArray(function (err, results) {
1790 callback(err, results.length);
180 });
181 });
182 };
183
184
185 //-------------------------------------------------------------------------
186 //
187 // Private Methods
188 //
189 //-------------------------------------------------------------------------
190
1910 function getOperation(type){
1920 return operations.getOperation(type);
193 }
194
1950 function logOptions(options) {
1960 if (!_.isEmpty(options)) {
1970 logger.debug('Options are', options);
198 }
199 }
200
2010 function updateFoundItems(options, results, update, callback) {
2020 if (!options.multi) {
2030 results = [results[0]];
204 }
2050 if (!options['new']) {
206 //Return original docs if new not specified.
2070 var originals = _.clone(results);
2080 updateResults(results, update, options);
2090 callback(null, options.modify ? originals : originals.length);
210 } else {
211 //Return modified items
2120 updateResults(results, update, options);
2130 callback(null, options.modify ? results : results.length);
214 }
215 }
216
2170 function updateResults(results, update, options) {
2180 _.each(results, function (result) {
2190 updateResult(result, update, options);
2200 db[name][result._id] = result;
221 });
222 }
223
2240 function updateResult(result, update, options) {
2250 _.forIn(update, function (update, type) {
2260 getOperation(type)(result, update, options);
227 });
228 }
229}
230

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/Logger.js

100%
4
4
0
LineHitsSource
11'use strict';
2
31var bunyan = require('bunyan');
4
51exports = module.exports = (function Logger(){
61 return bunyan.createLogger({name:'Mockgoose'});
7})();

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/Model.js

44%
9
4
5
LineHitsSource
11'use strict';
21var db = require('./db');
3
41var Collection = require('./Collection');
5
6//-------------------------------------------------------------------------
7//
8// Public Methods
9//
10//-------------------------------------------------------------------------
11
121module.exports = function (Model) {
13
14 /**
15 * Mockgoose method to allow resetting of the db.
16 * reset() will wipe the entire database.
17 * reset('schema name') will remove all models associated with the schema.
18 * @param type
19 * @returns {boolean}
20 */
210 Model.reset = function (type) {
220 return db.reset(type);
23 };
24
25
26 //-------------------------------------------------------------------------
27 //
28 // Private Methods that mimic the mongoose api overriding the default driver
29 //
30 //-------------------------------------------------------------------------
31
320 Model.prototype.collection = new Collection(Model.prototype.collection, Model);
330 Model.collection = Model.prototype.collection;
34
350 return Model;
36};
37
38

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/db.js

83%
12
10
2
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
41var models = {};
51module.exports = models;
6
71module.exports.reset = reset;
8
91function reset(type) {
102 if (!type) {
112 _.map(models, function(value, key){
122 if(key !== 'reset'){
130 delete models[key];
14 }
15 });
16 } else {
170 delete models[type];
18 }
192 return true;
20}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/AddToSetOperation.js

26%
15
4
11
LineHitsSource
11'use strict';
2
31var logger = require('../Logger');
41var _ = require('lodash');
5/*jshint -W098 *///options
61module.exports = function addToSetOperation(model, update, options) {
70 _.forIn(update, function (value, key) {
80 if(_.isObject(value) && value.$each){
90 var obj = {};
100 obj[key] = value.$each;
110 addToSetOperation(model, obj, options);
12 }else{
130 var original = model[key];
140 if (_.isArray(original)) {
150 if (!_.isArray(value)) {
160 value = [value];
17 }
180 model[key] = _.union(original, value);
19 } else {
200 logger.warn('$addToSet model value not an array', key);
21 }
22 }
23 });
24};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/AllOperation.js

44%
9
4
5
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
41var operations = require('./Operations');
5
6/*jshint -W098 *///options
71module.exports = function operation(model, update, options) {
80 var results = _.every(update.$all, function (value) {
90 if(value.$elemMatch){
100 return operations.getOperation('$elemMatch')(model, value, options);
11 }
120 return _.contains(model[options.queryItem], value);
13 });
140 return results;
15};
16

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/ElemMatchOperation.js

33%
12
4
8
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
41var operations = require('./Operations');
5
6/*jshint -W098 *///options
71module.exports = function operation(model, update, options) {
80 var result = _.find(model[options.queryItem] || [model], function (item) {
90 return _.every(_.keys(update.$elemMatch), function (key) {
100 var value = update.$elemMatch[key];
110 if(operations.isOperation(value)){
120 return operations.getOperation(value)(item, value, {queryItem:key});
13 }
140 var equal = _.isEqual(item[key], value);
150 return equal;
16 });
17 });
18
190 return result;
20};
21

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/GreaterThanOperation.js

75%
4
3
1
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
4
5/*jshint -W098 *///options
61module.exports = function operation(model, update, options) {
70 return model[options.queryItem] > update.$gt;
8};
9

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/InOperation.js

40%
10
4
6
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
41var utils = require('../utils');
5/*jshint -W098 *///options
61module.exports = function inOperation(model, update, options) {
70 var modelValue = utils.findProperty(model, options.queryItem);
80 var contains = utils.contains;
90 return !!_.find(update.$in, function (value) {
100 if(contains(modelValue, value)){
110 return true;
12 }
130 return false;
14 });
15
16};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/IncOperation.js

60%
5
3
2
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
4/*jshint -W098 *///options
51module.exports = function incOperation(model, update, options) {
60 _.forIn(update, function (value, key) {
70 model[key] += value;
8 });
9};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/NEOperation.js

50%
8
4
4
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
41var inOperation = require('./InOperation');
5/*jshint -W098 *///options
61module.exports = function operation(model, update, options) {
70 var updateClone = _.defaults({}, update);
80 delete updateClone.$ne;
90 updateClone.$in = [update.$ne];
100 return !inOperation(model , updateClone, options);
11};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/Operations.js

38%
18
7
11
LineHitsSource
11'use strict';
2
31var logger = require('../Logger');
41var _ = require('lodash');
5
61var operations = {
7 '$pull': require('./PullOperation'),
8 '$pullAll': require('./PullAllOperation'),
9 '$push': require('./PushOperation'),
10 '$pushAll': require('./PushAllOperation'),
11 '$set': require('./SetOperation'),
12 '$inc': require('./IncOperation'),
13 '$addToSet' : require('./AddToSetOperation'),
14 '$in' : require('./InOperation'),
15 '$ne' : require('./NEOperation'),
16 '$elemMatch' : require('./ElemMatchOperation'),
17 '$all' : require('./AllOperation'),
18 '$gt' : require('./GreaterThanOperation'),
19 '$unset' : require('./UnsetOperation')
20};
21
221module.exports.isOperation = function(value){
230 value = module.exports.getOperationFromObject(value);
240 return !!operations[value];
25};
26
271module.exports.getOperationFromObject = function(value){
280 if(_.isObject(value)){
290 return _.find(_.keys(operations), function(operation){
300 return value[operation];
31 });
32 }
330 return value;
34};
35
361module.exports.getOperation = function getOperation(type){
370 var operation = module.exports.getOperationFromObject(type);
380 if(!operations[operation]){
390 logger.error('Mockgoose currently does not support the ' + operation + ' operation' );
400 return false;
41 }
420 return operations[operation];
43};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/PullAllOperation.js

44%
9
4
5
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
41var pull = require('./PullOperation');
5/*jshint -W098 *///options
61module.exports = function pullAllOperation(model, updates, options) {
70 _.forIn(updates, function (value, key) {
80 _.forEach(value, function(item){
90 var update = {};
100 update[key] = item;
110 pull(model, update, options);
12 });
13 });
14};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/PullOperation.js

16%
48
8
40
LineHitsSource
11'use strict';
2
31var utils = require('../utils');
41var _ = require('lodash');
5
6/*jshint -W098 *///options
71module.exports = function pullOperation(model, update, options) {
80 pullItems(model, update);
9};
10
11//-------------------------------------------------------------------------
12//
13// Private Methods
14//
15//-------------------------------------------------------------------------
16
171function pullItems(model, pulls) {
180 for (var pull in pulls) {
190 if (pulls.hasOwnProperty(pull)) {
200 var values = model[pull];
210 var match = utils.findMatch(values, pulls[pull]);
220 if (match.length > 0) {
230 pullItem(match, values);
24 }
25 }
26 }
27}
28
291function pullItem(match, values) {
300 for (var i in match) {
310 if (match.hasOwnProperty(i)) {
320 var index = indexOf(values, match[i]);
330 if (index > -1) {
340 values.splice(index, 1);
35 }
36 }
37 }
38}
39
401function indexOf(values, match) {
410 var index = -1;
420 var foundItem = _.find(values, function (value) {
430 index++;
440 return deepEquals(value, match);
45 });
460 if (foundItem) {
470 return index;
48 }
490 return -1;
50}
51
52/**
53 * Implementation from
54 * http://stackoverflow.com/questions/1068834/object-comparison-in-javascript
55 */
561function deepEquals(x, y) {
570 if (x === y) {
580 return true;
59 }
60 // if both x and y are null or undefined and exactly the same
61
620 if (!( x instanceof Object ) || !( y instanceof Object )) {
630 return false;
64
65 }
66 // if they are not strictly equal, they both need to be Objects
67
680 if (x.constructor !== y.constructor) {
690 return false;
70 }
71 // they must have the exact same prototype chain, the closest we can do is
72 // test there constructor.
73
740 for (var p in x) {
750 if (!x.hasOwnProperty(p)) {
760 continue;
77 }
78 // other properties were tested using x.constructor === y.constructor
79
800 if (!y.hasOwnProperty(p)) {
810 return false;
82 }
83 // allows to compare x[ p ] and y[ p ] when set to undefined
84
850 if (x[ p ] === y[ p ]) {
860 continue;
87 }
88 // if they have the same strict value or identity then they are equal
89
900 if (typeof( x[ p ] ) !== 'object') {
910 return false;
92 }
93 // Numbers, Strings, Functions, Booleans must be strictly equal
94
950 if (!deepEquals(x[ p ], y[ p ])) {
960 return false;
97 }
98 // Objects and Arrays must be tested recursively
99 }
100
1010 for (p in y) {
1020 if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) {
1030 return false;
104 }
105 // allows x[ p ] to be set to undefined
106 }
1070 return true;
108}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/PushAllOperation.js

44%
9
4
5
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
41var push = require('./PushOperation');
5/*jshint -W098 *///options
61module.exports = function pushAllOperation(model, updates, options) {
70 _.forIn(updates, function (value, key) {
80 _.forEach(value, function(item){
90 var update = {};
100 update[key] = item;
110 push(model, update, options);
12 });
13 });
14};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/PushOperation.js

25%
12
3
9
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
4/*jshint -W098 *///options
51module.exports = function pushOperation(model, update, options) {
60 _.forIn(update, function (value, key) {
70 var temp = [];
80 if (model[key]) {
90 temp = temp.concat(model[key]);
10 }
110 var updates = value;
120 if (updates.$each) {
130 temp = temp.concat(updates.$each);
14 } else {
150 temp.push(updates);
16 }
170 model[key] = temp;
18 });
19};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/SetOperation.js

60%
5
3
2
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
4/*jshint -W098 *///options
51module.exports = function setOperation(model, update, options) {
60 _.forIn(update, function (value, key) {
70 model[key] = value;
8 });
9};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/operations/UnsetOperation.js

60%
5
3
2
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
4/*jshint -W098 *///options
51module.exports = function unsetOperation(model, update, options) {
60 _.forIn(update, function (value, key) {
70 delete model[key];
8 });
9};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/options/Filter.js

13%
30
4
26
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
41var mask = require('mongoosemask');
5
61module.exports = function filterFields(fields, results) {
70 var includes = [];
80 var excludes = [];
90 if (fields) {
100 if (_.isObject(fields)) {
110 _.forIn(fields, function (value, key) {
120 if (!!value ) {
130 includes.push(key);
14 } else {
150 excludes.push(key);
16 }
17 });
180 } else if (_.isString(fields)) {
190 _.each(fields.split(' '), function (field) {
200 if (field.indexOf('-') > -1) {
210 excludes.push(field.slice(1));
22 } else {
230 includes.push(field);
24 }
25 });
26 } else {
270 throw new Error('Fields must be a string or an object!');
28 }
29 }
300 if(includes.length && excludes.length ){
310 var error = new Error('You cannot currently mix including and excluding fields. Contact us if this is an issue.');
320 error.name = 'MongoError';
330 return error;
34 }
35
360 if (includes.length || excludes.length) {
370 results = _.map(results, function (result) {
380 if (includes.length) {
390 result = mask.expose(result, includes);
40 }
410 if (excludes.length) {
420 result = mask.mask(result, excludes);
43 }
440 return result;
45 });
46 }
470 return results;
48};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/options/Options.js

35%
20
7
13
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
41var filter = require('./Filter');
51var sort = require('./Sort');
61var operations = require('../operations/Operations');
7
81module.exports.applyOptions = function applyOptions(options, items) {
90 if (!_.isNull(options) && !_.isUndefined(options)) {
100 items = sort(options.sort, items);
110 items = filter(options.fields, items);
120 items = applyOperations(options.fields, items);
13 }
140 return items;
15};
16
171function applyOperations(fields, items) {
180 if (_.isObject(fields)) {
190 _.each(items, function (item) {
200 _.each(_.keys(fields), function (key) {
210 var value = fields[key];
220 if (operations.isOperation(value)) {
230 item[key] = _.find(item[key], function (element) {
240 return operations.getOperation(value)(element, value, {queryItem: key});
25 });
26 }
27 });
28 });
29 }
300 return items;
31}
32
33

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/options/Sort.js

22%
27
6
21
LineHitsSource
11'use strict';
2
31var _ = require('lodash');
4
51module.exports = function sortItems(sort, items) {
60 var item = items[0];
70 if (!_.isUndefined(item) && !_.isUndefined(sort)) {
80 _.forIn(sort, function (value, key) {
90 if (item[key]) {
100 if (_.isNumber(item[key])) {
110 sortNumeric(value, items, key);
12 }
130 else if(item[key] instanceof Date) {
140 sortDate(value, items, key);
15 }
16 else {
170 sortAlpha(value, items, key);
18 }
19 }
20 });
21 }
220 return items;
23};
24
25//-------------------------------------------------------------------------
26//
27// Private Methods
28//
29//-------------------------------------------------------------------------
30
311function sortDate(value, items, key){
320 return sortNumeric(value, items, key);
33}
34
351function sortNumeric(value, items, key) {
360 if (value === 1) {
370 items.sort(function (a, b) {
380 return a[key] - b[key];
39 });
40 } else {
410 items.sort(function (a, b) {
420 return b[key] - a[key];
43 });
44 }
45}
46
471function sortAlpha(value, items, key) {
480 if (value === 1) {
490 items.sort(function (a, b) {
500 return a[key].localeCompare(b[key]);
51 });
52 } else {
530 items.sort(function (a, b) {
540 return b[key].localeCompare(a[key]);
55 });
56 }
57}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/utils.js

27%
114
31
83
LineHitsSource
11'use strict';
21var _ = require('lodash');
31var operations = require('./operations/Operations');
4
51module.exports.isEmpty = _.isEmpty;
61module.exports.objectToArray = objectToArray;
71module.exports.cloneItems = cloneItems;
81module.exports.cloneItem = cloneItem;
91module.exports.matchParams = matchParams;
101module.exports.allParamsMatch = allParamsMatch;
111module.exports.buildResults = buildResults;
121module.exports.findMatch = findMatch;
131module.exports.foundModel = foundModel;
141module.exports.findModelQuery = findModelQuery;
151module.exports.findProperty = findProperty;
161module.exports.contains = contains;
17
18//-------------------------------------------------------------------------
19//
20// Private Methods
21//
22//-------------------------------------------------------------------------
23
241function findModelQuery(items, query) {
250 return findMatch(items, query);
26}
27
281function findMatch(items, query) {
290 var results = {};
300 for (var key in items) {
310 if (items.hasOwnProperty(key)) {
320 for (var q in query) {
330 buildResults(query, q, items, key, results);
34 }
35 }
36 }
370 return objectToArray(cloneItems(results));
38}
39
401function buildResults(query, q, items, key, results) {
410 if (query.hasOwnProperty(q)) {
420 var item = foundModel(items[key], query, q);
430 if (item) {
440 if (item._id) {
450 results[item._id] = item;
46 } else {
470 results[Math.random()] = item;
48 }
49 }
50 }
51}
52
531function foundModel(item, query, q) {
540 if (matchParams(item, query, q)) {
550 var allMatch = allParamsMatch(query, item);
560 if (allMatch) {
570 return item;//return cloneItem(item);
58 }
59 }
600 return false;
61}
62
631function contains(obj, target) {
640 if (!obj) {
650 return false;
66 }
670 if (typeof obj === 'object') {
680 obj = JSON.stringify(obj);
69 }
700 return obj.indexOf(target) !== -1;
71}
72
731function allParamsMatch(query, item) {
740 var allMatch = true;
750 for (var qq in query) {
760 if (query.hasOwnProperty(qq)) {
770 if (!matchParams(item, query, qq)) {
780 allMatch = false;
790 break;
80 }
81 }
82 }
830 return allMatch;
84}
85
861function findValue(objectPath, obj) {
870 var objPath = objectPath.split('.');
88 //Find our value.
890 var value = objectPath;
900 for (var k = 0; k < objPath.length; k++) {
910 value = obj[objPath[k]];
920 obj = value;
930 if (_.isUndefined(obj)) {
940 break;
950 } else if(_.isArray(obj)){
960 var values = _.pluck(obj, objPath[k+1]);
970 if(!_.isUndefined(values[0])){
980 value = values;
990 break;
100 }
101 }
102 }
1030 return value;
104}
105
1061function matchItems(value, queryItem, query, q, item) {
1070 var result = matchValues(value, queryItem);
1080 if (!result) {
1090 result = matchObjectParams(query, q, item);
110 }
1110 if (!result) {
1120 result = matchArrayParams(value, queryItem, query, q, item);
113 }
1140 return result;
115}
116
1171function matchParams(item, query, q) {
1180 var value = findValue(q, item);
1190 var queryItem = query[q];
1200 var result = matchItems(value, queryItem, query, q, item);
1210 return result;
122}
123
1241function matchValues(item, value) {
1250 return _.isEqual(item,value);
126}
127
1281function findProperty(item, q){
1290 var values = q.split('.');
1300 var value = item;
1310 _.each(values, function(prop){
1320 value = value[prop];
133 });
1340 return value;
135}
136
1371function matchObjectParams(query, q, item) {
1380 var result = false;
1390 if (typeof query[q] === 'object') {
1400 _.each(_.keys(query[q]), function(key){
1410 if(operations.isOperation(key)){
1420 result = operations.getOperation(key)(result || item, query[q], {query:query, queryItem:q});
1430 }else if(operations.isOperation(query[q][key])){
1440 result = operations.getOperation(query[q][key])(result || item, query[q][key], {query:query, queryItem:key});
1450 }else if (item[q] && query[q]) {
1460 if (item[q].toString() === query[q].toString()) {
1470 result = true;
148 }
149 }
150 });
151 }
1520 return result;
153}
154
1551function matchArrayParams(items, queryItem, query, q){
1560 if(_.isArray(items)){
1570 return _.any(items, function(item){
1580 return matchItems(item, queryItem, query, q, item);
159 });
160 }
1610 return false;
162}
163
1641function objectToArray(items) {
1650 var results = [];
1660 for (var model in items) {
1670 results.push(items[model]);
168 }
1690 return results;
170}
171
1721function cloneItems(items) {
1730 var clones = {};
1740 for (var item in items) {
1750 clones[item] = cloneItem(items[item]);
176 }
1770 return clones;
178}
179
1801function cloneItem(item) {
1810 return _.clone(item);
182}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/lib/validation/Validation.js

30%
26
8
18
LineHitsSource
11'use strict';
2
31var db = require('./../db');
41var util = require('util');
51var utils = require('./../utils');
61var _ = require('lodash');
7
8/**
9 * Duplicate path validation.
10 * @type {Function}
11 */
121module.exports.validate = validateOptions;
13
14
151function validatePath(doc, schema, pathName, type, error) {
160 var path = schema.paths[pathName];
170 if (path.options.unique) {
180 var query = {};
190 query[pathName] = doc[pathName];
200 var results = utils.findModelQuery(db[type], query);
210 if (results.length > 0) {
220 var errMessage = util.format('E11000 duplicate key error index: %s', pathName);
230 var code = 11000;
240 error = new Error(errMessage, code);
250 error.name = 'MongoError';
260 error.code = code;
270 return error;
28 }
29 }
300 return error;
31}
32
331function validateOptions(type, doc, schema, cb) {
340 var error = null;
350 if (!db[type][doc._id.toString()]) {
360 _.forIn(schema.paths, function(value, pathName){
370 error = validatePath(doc, schema, pathName, type, error);
38 });
39 }
400 cb(error);
41}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/bunyan/lib/bunyan.js

36%
549
203
346
LineHitsSource
1/*
2 * Copyright (c) 2013 Trent Mick. All rights reserved.
3 *
4 * The bunyan logging library for node.js.
5 */
6
71var VERSION = '0.22.1';
8
9// Bunyan log format version. This becomes the 'v' field on all log records.
10// `0` is until I release a version '1.0.0' of node-bunyan. Thereafter,
11// starting with `1`, this will be incremented if there is any backward
12// incompatible change to the log record format. Details will be in
13// 'CHANGES.md' (the change log).
141var LOG_VERSION = 0;
15
16
171var xxx = function xxx(s) { // internal dev/debug logging
180 var args = ['XX' + 'X: '+s].concat(
19 Array.prototype.slice.call(arguments, 1));
200 console.error.apply(this, args);
21};
221var xxx = function xxx() {}; // comment out to turn on debug logging
23
24
251var os = require('os');
261var fs = require('fs');
271var util = require('util');
281var assert = require('assert');
291try {
301 var dtrace = require('dtrace-provider');
31} catch (e) {
320 dtrace = null;
33}
341var EventEmitter = require('events').EventEmitter;
35
36// The 'mv' module is required for rotating-file stream support.
371try {
381 var mv = require('mv');
39} catch (e) {
400 mv = null;
41}
42
43
44
45//---- Internal support stuff
46
471function objCopy(obj) {
483 if (obj === null) {
490 return null;
503 } else if (Array.isArray(obj)) {
510 return obj.slice();
52 } else {
533 var copy = {};
543 Object.keys(obj).forEach(function (k) {
558 copy[k] = obj[k];
56 });
573 return copy;
58 }
59}
60
611var format = util.format;
621if (!format) {
63 // If node < 0.6, then use its `util.format`:
64 // <https://github.com/joyent/node/blob/master/lib/util.js#L22>:
650 var inspect = util.inspect;
660 var formatRegExp = /%[sdj%]/g;
670 format = function format(f) {
680 if (typeof (f) !== 'string') {
690 var objects = [];
700 for (var i = 0; i < arguments.length; i++) {
710 objects.push(inspect(arguments[i]));
72 }
730 return objects.join(' ');
74 }
75
760 var i = 1;
770 var args = arguments;
780 var len = args.length;
790 var str = String(f).replace(formatRegExp, function (x) {
800 if (i >= len)
810 return x;
820 switch (x) {
830 case '%s': return String(args[i++]);
840 case '%d': return Number(args[i++]);
850 case '%j': return JSON.stringify(args[i++], safeCycles());
860 case '%%': return '%';
87 default:
880 return x;
89 }
90 });
910 for (var x = args[i]; i < len; x = args[++i]) {
920 if (x === null || typeof (x) !== 'object') {
930 str += ' ' + x;
94 } else {
950 str += ' ' + inspect(x);
96 }
97 }
980 return str;
99 };
100}
101
102
103/**
104 * Gather some caller info 3 stack levels up.
105 * See <http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi>.
106 */
1071function getCaller3Info() {
1080 var obj = {};
1090 var saveLimit = Error.stackTraceLimit;
1100 var savePrepare = Error.prepareStackTrace;
1110 Error.stackTraceLimit = 3;
1120 Error.captureStackTrace(this, getCaller3Info);
1130 Error.prepareStackTrace = function (_, stack) {
1140 var caller = stack[2];
1150 obj.file = caller.getFileName();
1160 obj.line = caller.getLineNumber();
1170 var func = caller.getFunctionName();
1180 if (func)
1190 obj.func = func;
120 };
1210 this.stack;
1220 Error.stackTraceLimit = saveLimit;
1230 Error.prepareStackTrace = savePrepare;
1240 return obj;
125}
126
127
128/**
129 * Warn about an bunyan processing error.
130 *
131 * If file/line are given, this makes an attempt to warn on stderr only once.
132 *
133 * @param msg {String} Message with which to warn.
134 * @param file {String} Optional. File path relevant for the warning.
135 * @param line {String} Optional. Line number in `file` path relevant for
136 * the warning.
137 */
1381function _warn(msg, file, line) {
1390 assert.ok(msg);
1400 var key;
1410 if (file && line) {
1420 key = file + ':' + line;
1430 if (_warned[key]) {
1440 return;
145 }
1460 _warned[key] = true;
147 }
1480 process.stderr.write(msg + '\n');
149}
1501var _warned = {};
151
152
153
154//---- Levels
155
1561var TRACE = 10;
1571var DEBUG = 20;
1581var INFO = 30;
1591var WARN = 40;
1601var ERROR = 50;
1611var FATAL = 60;
162
1631var levelFromName = {
164 'trace': TRACE,
165 'debug': DEBUG,
166 'info': INFO,
167 'warn': WARN,
168 'error': ERROR,
169 'fatal': FATAL
170};
171
172// Dtrace probes.
1731var dtp = undefined;
1741var probes = dtrace && {};
175
176/**
177 * Resolve a level number, name (upper or lowercase) to a level number value.
178 *
179 * @api public
180 */
1811function resolveLevel(nameOrNum) {
1821 var level = (typeof (nameOrNum) === 'string'
183 ? levelFromName[nameOrNum.toLowerCase()]
184 : nameOrNum);
1851 if (! (TRACE <= level && level <= FATAL)) {
1860 throw new Error('invalid level: ' + nameOrNum);
187 }
1881 return level;
189}
190
191
192
193//---- Logger class
194
195/**
196 * Create a Logger instance.
197 *
198 * @param options {Object} See documentation for full details. At minimum
199 * this must include a 'name' string key. Configuration keys:
200 * - `streams`: specify the logger output streams. This is an array of
201 * objects with these fields:
202 * - `type`: The stream type. See README.md for full details.
203 * Often this is implied by the other fields. Examples are
204 * 'file', 'stream' and "raw".
205 * - `level`: Defaults to 'info'.
206 * - `path` or `stream`: The specify the file path or writeable
207 * stream to which log records are written. E.g.
208 * `stream: process.stdout`.
209 * - `closeOnExit` (boolean): Optional. Default is true for a
210 * 'file' stream when `path` is given, false otherwise.
211 * See README.md for full details.
212 * - `level`: set the level for a single output stream (cannot be used
213 * with `streams`)
214 * - `stream`: the output stream for a logger with just one, e.g.
215 * `process.stdout` (cannot be used with `streams`)
216 * - `serializers`: object mapping log record field names to
217 * serializing functions. See README.md for details.
218 * - `src`: Boolean (default false). Set true to enable 'src' automatic
219 * field with log call source info.
220 * All other keys are log record fields.
221 *
222 * An alternative *internal* call signature is used for creating a child:
223 * new Logger(<parent logger>, <child options>[, <child opts are simple>]);
224 *
225 * @param _childSimple (Boolean) An assertion that the given `_childOptions`
226 * (a) only add fields (no config) and (b) no serialization handling is
227 * required for them. IOW, this is a fast path for frequent child
228 * creation.
229 */
2301function Logger(options, _childOptions, _childSimple) {
2311 xxx('Logger start:', options)
2321 if (! this instanceof Logger) {
2330 return new Logger(options, _childOptions);
234 }
235
236 // Input arg validation.
2371 var parent;
2381 if (_childOptions !== undefined) {
2390 parent = options;
2400 options = _childOptions;
2410 if (! parent instanceof Logger) {
2420 throw new TypeError(
243 'invalid Logger creation: do not pass a second arg');
244 }
245 }
2461 if (!options) {
2470 throw new TypeError('options (object) is required');
248 }
2491 if (!parent) {
2501 if (!options.name) {
2510 throw new TypeError('options.name (string) is required');
252 }
253 } else {
2540 if (options.name) {
2550 throw new TypeError(
256 'invalid options.name: child cannot set logger name');
257 }
258 }
2591 if (options.stream && options.streams) {
2600 throw new TypeError('cannot mix "streams" and "stream" options');
261 }
2621 if (options.streams && !Array.isArray(options.streams)) {
2630 throw new TypeError('invalid options.streams: must be an array')
264 }
2651 if (options.serializers && (typeof (options.serializers) !== 'object' ||
266 Array.isArray(options.serializers))) {
2670 throw new TypeError('invalid options.serializers: must be an object')
268 }
269
2701 EventEmitter.call(this);
271
272 // Fast path for simple child creation.
2731 if (parent && _childSimple) {
274 // `_isSimpleChild` is a signal to stream close handling that this child
275 // owns none of its streams.
2760 this._isSimpleChild = true;
277
2780 this._level = parent._level;
2790 this.streams = parent.streams;
2800 this.serializers = parent.serializers;
2810 this.src = parent.src;
2820 var fields = this.fields = {};
2830 var parentFieldNames = Object.keys(parent.fields);
2840 for (var i = 0; i < parentFieldNames.length; i++) {
2850 var name = parentFieldNames[i];
2860 fields[name] = parent.fields[name];
287 }
2880 var names = Object.keys(options);
2890 for (var i = 0; i < names.length; i++) {
2900 var name = names[i];
2910 fields[name] = options[name];
292 }
2930 return;
294 }
295
296 // Null values.
2971 var self = this;
2981 if (parent) {
2990 this._level = parent._level;
3000 this.streams = [];
3010 for (var i = 0; i < parent.streams.length; i++) {
3020 var s = objCopy(parent.streams[i]);
3030 s.closeOnExit = false; // Don't own parent stream.
3040 this.streams.push(s);
305 }
3060 this.serializers = objCopy(parent.serializers);
3070 this.src = parent.src;
3080 this.fields = objCopy(parent.fields);
3090 if (options.level) {
3100 this.level(options.level);
311 }
312 } else {
3131 this._level = Number.POSITIVE_INFINITY;
3141 this.streams = [];
3151 this.serializers = null;
3161 this.src = false;
3171 this.fields = {};
318 }
319
3201 if (!dtp && dtrace) {
3211 dtp = dtrace.createDTraceProvider('bunyan');
322
3231 for (var level in levelFromName) {
3246 var probe;
325
3266 probes[levelFromName[level]] = probe =
327 dtp.addProbe('log-' + level, 'char *');
328
329 // Explicitly add a reference to dtp to prevent it from being GC'd
3306 probe.dtp = dtp;
331 }
332
3331 dtp.enable();
334 }
335
336 // Helpers
3371 function addStream(s) {
3381 s = objCopy(s);
339
340 // Implicit 'type' from other args.
3411 var type = s.type;
3421 if (!s.type) {
3430 if (s.stream) {
3440 s.type = 'stream';
3450 } else if (s.path) {
3460 s.type = 'file'
347 }
348 }
3491 s.raw = (s.type === 'raw'); // PERF: Allow for faster check in `_emit`.
350
3511 if (s.level) {
3521 s.level = resolveLevel(s.level);
3530 } else if (options.level) {
3540 s.level = resolveLevel(options.level);
355 } else {
3560 s.level = INFO;
357 }
3581 if (s.level < self._level) {
3591 self._level = s.level;
360 }
361
3621 switch (s.type) {
363 case 'stream':
3641 if (!s.closeOnExit) {
3651 s.closeOnExit = false;
366 }
3671 break;
368 case 'file':
3690 if (!s.stream) {
3700 s.stream = fs.createWriteStream(s.path,
371 {flags: 'a', encoding: 'utf8'});
3720 s.stream.on('error', function (err) {
3730 self.emit('error', err, s);
374 });
3750 if (!s.closeOnExit) {
3760 s.closeOnExit = true;
377 }
378 } else {
3790 if (!s.closeOnExit) {
3800 s.closeOnExit = false;
381 }
382 }
3830 break;
384 case 'rotating-file':
3850 assert.ok(!s.stream,
386 '"rotating-file" stream should not give a "stream"');
3870 assert.ok(s.path);
3880 assert.ok(mv, '"rotating-file" stream type is not supported: '
389 + 'missing "mv" module');
3900 s.stream = new RotatingFileStream(s);
3910 if (!s.closeOnExit) {
3920 s.closeOnExit = true;
393 }
3940 break;
395 case 'raw':
3960 if (!s.closeOnExit) {
3970 s.closeOnExit = false;
398 }
3990 break;
400 default:
4010 throw new TypeError('unknown stream type "' + s.type + '"');
402 }
403
4041 self.streams.push(s);
405 }
406
4071 function addSerializers(serializers) {
4080 if (!self.serializers) {
4090 self.serializers = {};
410 }
4110 Object.keys(serializers).forEach(function (field) {
4120 var serializer = serializers[field];
4130 if (typeof (serializer) !== 'function') {
4140 throw new TypeError(format(
415 'invalid serializer for "%s" field: must be a function',
416 field));
417 } else {
4180 self.serializers[field] = serializer;
419 }
420 });
421 }
422
423 // Handle *config* options (i.e. options that are not just plain data
424 // for log records).
4251 if (options.stream) {
4260 addStream({
427 type: 'stream',
428 stream: options.stream,
429 closeOnExit: false,
430 level: (options.level ? resolveLevel(options.level) : INFO)
431 });
4321 } else if (options.streams) {
4330 options.streams.forEach(addStream);
4341 } else if (parent && options.level) {
4350 this.level(options.level);
4361 } else if (!parent) {
4371 addStream({
438 type: 'stream',
439 stream: process.stdout,
440 closeOnExit: false,
441 level: (options.level ? resolveLevel(options.level) : INFO)
442 });
443 }
4441 if (options.serializers) {
4450 addSerializers(options.serializers);
446 }
4471 if (options.src) {
4480 this.src = true;
449 }
4501 xxx('Logger: ', self)
451
452 // Fields.
453 // These are the default fields for log records (minus the attributes
454 // removed in this constructor). To allow storing raw log records
455 // (unrendered), `this.fields` must never be mutated. Create a copy for
456 // any changes.
4571 var fields = objCopy(options);
4581 delete fields.stream;
4591 delete fields.level;
4601 delete fields.streams;
4611 delete fields.serializers;
4621 delete fields.src;
4631 if (this.serializers) {
4640 this._applySerializers(fields);
465 }
4661 if (!fields.hostname) {
4671 fields.hostname = os.hostname();
468 }
4691 if (!fields.pid) {
4701 fields.pid = process.pid;
471 }
4721 Object.keys(fields).forEach(function (k) {
4733 self.fields[k] = fields[k];
474 });
475}
476
4771util.inherits(Logger, EventEmitter);
478
479
480/**
481 * Create a child logger, typically to add a few log record fields.
482 *
483 * This can be useful when passing a logger to a sub-component, e.g. a
484 * 'wuzzle' component of your service:
485 *
486 * var wuzzleLog = log.child({component: 'wuzzle'})
487 * var wuzzle = new Wuzzle({..., log: wuzzleLog})
488 *
489 * Then log records from the wuzzle code will have the same structure as
490 * the app log, *plus the component='wuzzle' field*.
491 *
492 * @param options {Object} Optional. Set of options to apply to the child.
493 * All of the same options for a new Logger apply here. Notes:
494 * - The parent's streams are inherited and cannot be removed in this
495 * call. Any given `streams` are *added* to the set inherited from
496 * the parent.
497 * - The parent's serializers are inherited, though can effectively be
498 * overwritten by using duplicate keys.
499 * - Can use `level` to set the level of the streams inherited from
500 * the parent. The level for the parent is NOT affected.
501 * @param simple {Boolean} Optional. Set to true to assert that `options`
502 * (a) only add fields (no config) and (b) no serialization handling is
503 * required for them. IOW, this is a fast path for frequent child
504 * creation. See 'tools/timechild.js' for numbers.
505 */
5061Logger.prototype.child = function (options, simple) {
5070 return new Logger(this, options || {}, simple);
508}
509
510
511/**
512 * A convenience method to reopen 'file' streams on a logger. This can be
513 * useful with external log rotation utilities that move and re-open log files
514 * (e.g. logrotate on Linux, logadm on SmartOS/Illumos). Those utilities
515 * typically have rotation options to copy-and-truncate the log file, but
516 * you may not want to use that. An alternative is to do this in your
517 * application:
518 *
519 * var log = bunyan.createLogger(...);
520 * ...
521 * process.on('SIGUSR2', function () {
522 * log.reopenFileStreams();
523 * });
524 * ...
525 *
526 * See <https://github.com/trentm/node-bunyan/issues/104>.
527 */
5281Logger.prototype.reopenFileStreams = function () {
5290 var self = this;
5300 self.streams.forEach(function (s) {
5310 if (s.type === 'file') {
5320 if (s.stream) {
533 // Not sure if typically would want this, or more immediate
534 // `s.stream.destroy()`.
5350 s.stream.end();
5360 s.stream.destroySoon();
5370 delete s.stream;
538 }
5390 s.stream = fs.createWriteStream(s.path,
540 {flags: 'a', encoding: 'utf8'});
5410 s.stream.on('error', function (err) {
5420 self.emit('error', err, s);
543 });
544 }
545 });
546};
547
548
549/* BEGIN JSSTYLED */
550/**
551 * Close this logger.
552 *
553 * This closes streams (that it owns, as per 'endOnClose' attributes on
554 * streams), etc. Typically you **don't** need to bother calling this.
555Logger.prototype.close = function () {
556 if (this._closed) {
557 return;
558 }
559 if (!this._isSimpleChild) {
560 self.streams.forEach(function (s) {
561 if (s.endOnClose) {
562 xxx('closing stream s:', s);
563 s.stream.end();
564 s.endOnClose = false;
565 }
566 });
567 }
568 this._closed = true;
569}
570 */
571/* END JSSTYLED */
572
573
574/**
575 * Get/set the level of all streams on this logger.
576 *
577 * Get Usage:
578 * // Returns the current log level (lowest level of all its streams).
579 * log.level() -> INFO
580 *
581 * Set Usage:
582 * log.level(INFO) // set all streams to level INFO
583 * log.level('info') // can use 'info' et al aliases
584 */
5851Logger.prototype.level = function level(value) {
5860 if (value === undefined) {
5870 return this._level;
588 }
5890 var newLevel = resolveLevel(value);
5900 var len = this.streams.length;
5910 for (var i = 0; i < len; i++) {
5920 this.streams[i].level = newLevel;
593 }
5940 this._level = newLevel;
595}
596
597
598/**
599 * Get/set the level of a particular stream on this logger.
600 *
601 * Get Usage:
602 * // Returns an array of the levels of each stream.
603 * log.levels() -> [TRACE, INFO]
604 *
605 * // Returns a level of the identified stream.
606 * log.levels(0) -> TRACE // level of stream at index 0
607 * log.levels('foo') // level of stream with name 'foo'
608 *
609 * Set Usage:
610 * log.levels(0, INFO) // set level of stream 0 to INFO
611 * log.levels(0, 'info') // can use 'info' et al aliases
612 * log.levels('foo', WARN) // set stream named 'foo' to WARN
613 *
614 * Stream names: When streams are defined, they can optionally be given
615 * a name. For example,
616 * log = new Logger({
617 * streams: [
618 * {
619 * name: 'foo',
620 * path: '/var/log/my-service/foo.log'
621 * level: 'trace'
622 * },
623 * ...
624 *
625 * @param name {String|Number} The stream index or name.
626 * @param value {Number|String} The level value (INFO) or alias ('info').
627 * If not given, this is a 'get' operation.
628 * @throws {Error} If there is no stream with the given name.
629 */
6301Logger.prototype.levels = function levels(name, value) {
6310 if (name === undefined) {
6320 assert.equal(value, undefined);
6330 return this.streams.map(
6340 function (s) { return s.level });
635 }
6360 var stream;
6370 if (typeof (name) === 'number') {
6380 stream = this.streams[name];
6390 if (stream === undefined) {
6400 throw new Error('invalid stream index: ' + name);
641 }
642 } else {
6430 var len = this.streams.length;
6440 for (var i = 0; i < len; i++) {
6450 var s = this.streams[i];
6460 if (s.name === name) {
6470 stream = s;
6480 break;
649 }
650 }
6510 if (!stream) {
6520 throw new Error(format('no stream with name "%s"', name));
653 }
654 }
6550 if (value === undefined) {
6560 return stream.level;
657 } else {
6580 var newLevel = resolveLevel(value);
6590 stream.level = newLevel;
6600 if (newLevel < this._level) {
6610 this._level = newLevel;
662 }
663 }
664}
665
666
667/**
668 * Apply registered serializers to the appropriate keys in the given fields.
669 *
670 * Pre-condition: This is only called if there is at least one serializer.
671 *
672 * @param fields (Object) The log record fields.
673 * @param excludeFields (Object) Optional mapping of keys to `true` for
674 * keys to NOT apply a serializer.
675 */
6761Logger.prototype._applySerializers = function (fields, excludeFields) {
6770 var self = this;
678
6790 xxx('_applySerializers: excludeFields', excludeFields);
680
681 // Check each serializer against these (presuming number of serializers
682 // is typically less than number of fields).
6830 Object.keys(this.serializers).forEach(function (name) {
6840 if (fields[name] === undefined ||
685 (excludeFields && excludeFields[name]))
686 {
6870 return;
688 }
6890 xxx('_applySerializers; apply to "%s" key', name)
6900 try {
6910 fields[name] = self.serializers[name](fields[name]);
692 } catch (err) {
6930 _warn(format('bunyan: ERROR: This should never happen. '
694 + 'This is a bug in <https://github.com/trentm/node-bunyan> '
695 + 'or in this application. Exception from "%s" Logger '
696 + 'serializer: %s',
697 name, err.stack || err));
6980 fields[name] = format('(Error in Bunyan log "%s" serializer '
699 + 'broke field. See stderr for details.)', name);
700 }
701 });
702}
703
704
705/**
706 * Emit a log record.
707 *
708 * @param rec {log record}
709 * @param noemit {Boolean} Optional. Set to true to skip emission
710 * and just return the JSON string.
711 */
7121Logger.prototype._emit = function (rec, noemit) {
7131 var i;
714
715 // Lazily determine if this Logger has non-'raw' streams. If there are
716 // any, then we need to stringify the log record.
7171 if (this.haveNonRawStreams === undefined) {
7181 this.haveNonRawStreams = false;
7191 for (i = 0; i < this.streams.length; i++) {
7201 if (!this.streams[i].raw) {
7211 this.haveNonRawStreams = true;
7221 break;
723 }
724 }
725 }
726
727 // Stringify the object. Attempt to warn/recover on error.
7281 var str;
7291 if (noemit || this.haveNonRawStreams) {
7301 str = JSON.stringify(rec, safeCycles()) + '\n';
731 }
732
7331 if (noemit)
7340 return str;
735
7361 var level = rec.level;
7371 for (i = 0; i < this.streams.length; i++) {
7381 var s = this.streams[i];
7391 if (s.level <= level) {
7401 xxx('writing log rec "%s" to "%s" stream (%d <= %d): %j',
741 rec.msg, s.type, s.level, level, rec);
7421 s.stream.write(s.raw ? rec : str);
743 }
744 };
745
7461 return str;
747}
748
749
750/**
751 * Build a log emitter function for level minLevel. I.e. this is the
752 * creator of `log.info`, `log.error`, etc.
753 */
7541function mkLogEmitter(minLevel) {
7556 return function () {
7561 var log = this;
757
7581 function mkRecord(args) {
7591 var excludeFields;
7601 if (args[0] instanceof Error) {
761 // `log.<level>(err, ...)`
7620 fields = {err: errSerializer(args[0])};
7630 excludeFields = {err: true};
7640 if (args.length === 1) {
7650 msgArgs = [fields.err.message];
766 } else {
7670 msgArgs = Array.prototype.slice.call(args, 1);
768 }
7691 } else if (typeof (args[0]) === 'string') {
770 // `log.<level>(msg, ...)`
7711 fields = null;
7721 msgArgs = Array.prototype.slice.call(args);
7730 } else if (Buffer.isBuffer(args[0])) { // `log.<level>(buf, ...)`
774 // Almost certainly an error, show `inspect(buf)`. See bunyan
775 // issue #35.
7760 fields = null;
7770 msgArgs = Array.prototype.slice.call(args);
7780 msgArgs[0] = util.inspect(msgArgs[0]);
779 } else { // `log.<level>(fields, msg, ...)`
7800 fields = args[0];
7810 msgArgs = Array.prototype.slice.call(args, 1);
782 }
783
784 // Build up the record object.
7851 var rec = objCopy(log.fields);
7861 var level = rec.level = minLevel;
7871 var recFields = (fields ? objCopy(fields) : null);
7881 if (recFields) {
7890 if (log.serializers) {
7900 log._applySerializers(recFields, excludeFields);
791 }
7920 Object.keys(recFields).forEach(function (k) {
7930 rec[k] = recFields[k];
794 });
795 }
7961 rec.msg = format.apply(log, msgArgs);
7971 if (!rec.time) {
7981 rec.time = (new Date());
799 }
800 // Get call source info
8011 if (log.src && !rec.src) {
8020 rec.src = getCaller3Info()
803 }
8041 rec.v = LOG_VERSION;
805
8061 return rec;
807 };
808
8091 var fields = null;
8101 var msgArgs = arguments;
8111 var str = null;
8121 var rec = null;
8131 if (arguments.length === 0) { // `log.<level>()`
8140 return (this._level <= minLevel);
8151 } else if (this._level > minLevel) {
816 /* pass through */
817 } else {
8181 rec = mkRecord(msgArgs);
8191 str = this._emit(rec);
820 }
8211 probes && probes[minLevel].fire(function () {
8220 return [ str ||
823 (rec && log._emit(rec, true)) ||
824 log._emit(mkRecord(msgArgs), true) ];
825 });
826 }
827}
828
829
830/**
831 * The functions below log a record at a specific level.
832 *
833 * Usages:
834 * log.<level>() -> boolean is-trace-enabled
835 * log.<level>(<Error> err, [<string> msg, ...])
836 * log.<level>(<string> msg, ...)
837 * log.<level>(<object> fields, <string> msg, ...)
838 *
839 * where <level> is the lowercase version of the log level. E.g.:
840 *
841 * log.info()
842 *
843 * @params fields {Object} Optional set of additional fields to log.
844 * @params msg {String} Log message. This can be followed by additional
845 * arguments that are handled like
846 * [util.format](http://nodejs.org/docs/latest/api/all.html#util.format).
847 */
8481Logger.prototype.trace = mkLogEmitter(TRACE);
8491Logger.prototype.debug = mkLogEmitter(DEBUG);
8501Logger.prototype.info = mkLogEmitter(INFO);
8511Logger.prototype.warn = mkLogEmitter(WARN);
8521Logger.prototype.error = mkLogEmitter(ERROR);
8531Logger.prototype.fatal = mkLogEmitter(FATAL);
854
855
856
857//---- Standard serializers
858// A serializer is a function that serializes a JavaScript object to a
859// JSON representation for logging. There is a standard set of presumed
860// interesting objects in node.js-land.
861
8621Logger.stdSerializers = {};
863
864// Serialize an HTTP request.
8651Logger.stdSerializers.req = function req(req) {
8660 if (!req || !req.connection)
8670 return req;
8680 return {
869 method: req.method,
870 url: req.url,
871 headers: req.headers,
872 remoteAddress: req.connection.remoteAddress,
873 remotePort: req.connection.remotePort
874 };
875 // Trailers: Skipping for speed. If you need trailers in your app, then
876 // make a custom serializer.
877 //if (Object.keys(trailers).length > 0) {
878 // obj.trailers = req.trailers;
879 //}
880};
881
882// Serialize an HTTP response.
8831Logger.stdSerializers.res = function res(res) {
8840 if (!res || !res.statusCode)
8850 return res;
8860 return {
887 statusCode: res.statusCode,
888 header: res._header
889 }
890};
891
892
893/*
894 * This function dumps long stack traces for exceptions having a cause()
895 * method. The error classes from
896 * [verror](https://github.com/davepacheco/node-verror) and
897 * [restify v2.0](https://github.com/mcavage/node-restify) are examples.
898 *
899 * Based on `dumpException` in
900 * https://github.com/davepacheco/node-extsprintf/blob/master/lib/extsprintf.js
901 */
9021function getFullErrorStack(ex)
903{
9040 var ret = ex.stack || ex.toString();
9050 if (ex.cause && typeof (ex.cause) === 'function') {
9060 var cex = ex.cause();
9070 if (cex) {
9080 ret += '\nCaused by: ' + getFullErrorStack(cex);
909 }
910 }
9110 return (ret);
912}
913
914// Serialize an Error object
915// (Core error properties are enumerable in node 0.4, not in 0.6).
9161var errSerializer = Logger.stdSerializers.err = function err(err) {
9170 if (!err || !err.stack)
9180 return err;
9190 var obj = {
920 message: err.message,
921 name: err.name,
922 stack: getFullErrorStack(err),
923 code: err.code,
924 signal: err.signal
925 }
9260 return obj;
927};
928
929
930// A JSON stringifier that handles cycles safely.
931// Usage: JSON.stringify(obj, safeCycles())
9321function safeCycles() {
9331 var seen = [];
9341 return function (key, val) {
9358 if (!val || typeof (val) !== 'object') {
9367 return val;
937 }
9381 if (seen.indexOf(val) !== -1) {
9390 return '[Circular]';
940 }
9411 seen.push(val);
9421 return val;
943 };
944}
945
946
947/**
948 * XXX
949 */
9501if (mv) {
951
9521function RotatingFileStream(options) {
9530 this.path = options.path;
9540 this.stream = fs.createWriteStream(this.path,
955 {flags: 'a', encoding: 'utf8'});
9560 this.count = (options.count == null ? 10 : options.count);
9570 assert.ok(typeof (this.count) === 'number' && this.count >= 0);
958
959 // Parse `options.period`.
9600 if (options.period) {
961 // <number><scope> where scope is:
962 // h hours (at the start of the hour)
963 // d days (at the start of the day, i.e. just after midnight)
964 // w weeks (at the start of Sunday)
965 // m months (on the first of the month)
966 // y years (at the start of Jan 1st)
967 // with special values 'hourly' (1h), 'daily' (1d), "weekly" (1w),
968 // 'monthly' (1m) and 'yearly' (1y)
9690 var period = {
970 'hourly': '1h',
971 'daily': '1d',
972 'weekly': '1w',
973 'monthly': '1m',
974 'yearly': '1y'
975 }[options.period] || options.period;
9760 var m = /^([1-9][0-9]*)([hdwmy]|ms)$/.exec(period);
9770 if (!m) {
9780 throw new Error(format('invalid period: "%s"', options.period));
979 }
9800 this.periodNum = Number(m[1]);
9810 this.periodScope = m[2];
982 } else {
9830 this.periodNum = 1;
9840 this.periodScope = 'd';
985 }
986
987 // TODO: template support for backup files
988 // template: <path to which to rotate>
989 // default is %P.%n
990 // '/var/log/archive/foo.log' -> foo.log.%n
991 // '/var/log/archive/foo.log.%n'
992 // codes:
993 // XXX support strftime codes (per node version of those)
994 // or whatever module. Pick non-colliding for extra
995 // codes
996 // %P `path` base value
997 // %n integer number of rotated log (1,2,3,...)
998 // %d datetime in YYYY-MM-DD_HH-MM-SS
999 // XXX what should default date format be?
1000 // prior art? Want to avoid ':' in
1001 // filenames (illegal on Windows for one).
1002
10030 this.rotQueue = [];
10040 this.rotating = false;
10050 this._setupNextRot();
1006}
1007
10081util.inherits(RotatingFileStream, EventEmitter);
1009
10101RotatingFileStream.prototype._setupNextRot = function () {
10110 var self = this;
10120 this.rotAt = this._nextRotTime();
10130 this.timeout = setTimeout(
10140 function () { self.rotate(); },
1015 this.rotAt - Date.now());
1016}
1017
10181RotatingFileStream.prototype._nextRotTime = function _nextRotTime(first) {
10190 var _DEBUG = false;
10200 if (_DEBUG)
10210 console.log('-- _nextRotTime: %s%s', this.periodNum, this.periodScope);
10220 var d = new Date();
1023
10240 if (_DEBUG) console.log(' now local: %s', d);
10250 if (_DEBUG) console.log(' now utc: %s', d.toISOString());
10260 var rotAt;
10270 switch (this.periodScope) {
1028 case 'ms':
1029 // Hidden millisecond period for debugging.
10300 if (this.rotAt) {
10310 rotAt = this.rotAt + this.periodNum;
1032 } else {
10330 rotAt = Date.now() + this.periodNum;
1034 }
10350 break;
1036 case 'h':
10370 if (this.rotAt) {
10380 rotAt = this.rotAt + this.periodNum * 60 * 60 * 1000;
1039 } else {
1040 // First time: top of the next hour.
10410 rotAt = Date.UTC(d.getUTCFullYear(), d.getUTCMonth(),
1042 d.getUTCDate(), d.getUTCHours() + 1);
1043 }
10440 break;
1045 case 'd':
10460 if (this.rotAt) {
10470 rotAt = this.rotAt + this.periodNum * 24 * 60 * 60 * 1000;
1048 } else {
1049 // First time: start of tomorrow (i.e. at the coming midnight) UTC.
10500 rotAt = Date.UTC(d.getUTCFullYear(), d.getUTCMonth(),
1051 d.getUTCDate() + 1);
1052 }
10530 break;
1054 case 'w':
1055 // Currently, always on Sunday morning at 00:00:00 (UTC).
10560 if (this.rotAt) {
10570 rotAt = this.rotAt + this.periodNum * 7 * 24 * 60 * 60 * 1000;
1058 } else {
1059 // First time: this coming Sunday.
10600 rotAt = Date.UTC(d.getUTCFullYear(), d.getUTCMonth(),
1061 d.getUTCDate() + (7 - d.getUTCDay()));
1062 }
10630 break;
1064 case 'm':
10650 if (this.rotAt) {
10660 rotAt = Date.UTC(d.getUTCFullYear(),
1067 d.getUTCMonth() + this.periodNum, 1);
1068 } else {
1069 // First time: the start of the next month.
10700 rotAt = Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 1);
1071 }
10720 break;
1073 case 'y':
10740 if (this.rotAt) {
10750 rotAt = Date.UTC(d.getUTCFullYear() + this.periodNum, 0, 1);
1076 } else {
1077 // First time: the start of the next year.
10780 rotAt = Date.UTC(d.getUTCFullYear() + 1, 0, 1);
1079 }
10800 break;
1081 default:
10820 assert.fail(format('invalid period scope: "%s"', this.periodScope));
1083 }
1084
10850 if (_DEBUG) {
10860 console.log(' **rotAt**: %s (utc: %s)', rotAt,
1087 new Date(rotAt).toUTCString());
10880 var now = Date.now();
10890 console.log(' now: %s (%sms == %smin == %sh to go)',
1090 now,
1091 rotAt - now,
1092 (rotAt-now)/1000/60,
1093 (rotAt-now)/1000/60/60);
1094 }
10950 return rotAt;
1096};
1097
10981RotatingFileStream.prototype.rotate = function rotate() {
1099 // XXX What about shutdown?
11000 var self = this;
11010 var _DEBUG = false;
1102
11030 if (_DEBUG) console.log('-- [%s] rotating %s', new Date(), self.path);
11040 if (self.rotating) {
11050 throw new TypeError('cannot start a rotation when already rotating');
1106 }
11070 self.rotating = true;
1108
11090 self.stream.end(); // XXX can do moves sync after this? test at high rate
1110
11110 function del() {
11120 var toDel = self.path + '.' + String(n - 1);
11130 if (n === 0) {
11140 toDel = self.path;
1115 }
11160 n -= 1;
11170 if (_DEBUG) console.log('rm %s', toDel);
11180 fs.unlink(toDel, function (delErr) {
1119 //XXX handle err other than not exists
11200 moves();
1121 });
1122 }
1123
11240 function moves() {
11250 if (self.count === 0 || n < 0) {
11260 return finish();
1127 }
11280 var before = self.path;
11290 var after = self.path + '.' + String(n);
11300 if (n > 0) {
11310 before += '.' + String(n - 1);
1132 }
11330 n -= 1;
11340 fs.exists(before, function (exists) {
11350 if (!exists) {
11360 moves();
1137 } else {
11380 if (_DEBUG) console.log('mv %s %s', before, after);
11390 mv(before, after, function (mvErr) {
11400 if (mvErr) {
11410 self.emit('error', mvErr);
11420 finish(); // XXX finish here?
1143 } else {
11440 moves();
1145 }
1146 });
1147 }
1148 })
1149 }
1150
11510 function finish() {
11520 if (_DEBUG) console.log('open %s', self.path);
11530 self.stream = fs.createWriteStream(self.path,
1154 {flags: 'a', encoding: 'utf8'});
11550 var q = self.rotQueue, len = q.length;
11560 for (var i = 0; i < len; i++) {
11570 self.stream.write(q[i]);
1158 }
11590 self.rotQueue = [];
11600 self.rotating = false;
11610 self.emit('drain');
11620 self._setupNextRot();
1163 }
1164
11650 var n = this.count;
11660 del();
1167};
1168
11691RotatingFileStream.prototype.write = function write(s) {
11700 if (this.rotating) {
11710 this.rotQueue.push(s);
11720 return false;
1173 } else {
11740 return this.stream.write(s);
1175 }
1176};
1177
11781RotatingFileStream.prototype.end = function end(s) {
11790 this.stream.end();
1180};
1181
11821RotatingFileStream.prototype.destroy = function destroy(s) {
11830 this.stream.destroy();
1184};
1185
11861RotatingFileStream.prototype.destroySoon = function destroySoon(s) {
11870 this.stream.destroySoon();
1188};
1189
1190} /* if (mv) */
1191
1192
1193
1194/**
1195 * RingBuffer is a Writable Stream that just stores the last N records in
1196 * memory.
1197 *
1198 * @param options {Object}, with the following fields:
1199 *
1200 * - limit: number of records to keep in memory
1201 */
12021function RingBuffer(options) {
12030 this.limit = options && options.limit ? options.limit : 100;
12040 this.writable = true;
12050 this.records = [];
12060 EventEmitter.call(this);
1207}
1208
12091util.inherits(RingBuffer, EventEmitter);
1210
12111RingBuffer.prototype.write = function (record) {
12120 if (!this.writable)
12130 throw (new Error('RingBuffer has been ended already'));
1214
12150 this.records.push(record);
1216
12170 if (this.records.length > this.limit)
12180 this.records.shift();
1219
12200 return (true);
1221};
1222
12231RingBuffer.prototype.end = function () {
12240 if (arguments.length > 0)
12250 this.write.apply(this, Array.prototype.slice.call(arguments));
12260 this.writable = false;
1227};
1228
12291RingBuffer.prototype.destroy = function () {
12300 this.writable = false;
12310 this.emit('close');
1232};
1233
12341RingBuffer.prototype.destroySoon = function () {
12350 this.destroy();
1236};
1237
1238
1239//---- Exports
1240
12411module.exports = Logger;
1242
12431module.exports.TRACE = TRACE;
12441module.exports.DEBUG = DEBUG;
12451module.exports.INFO = INFO;
12461module.exports.WARN = WARN;
12471module.exports.ERROR = ERROR;
12481module.exports.FATAL = FATAL;
12491module.exports.resolveLevel = resolveLevel;
1250
12511module.exports.VERSION = VERSION;
12521module.exports.LOG_VERSION = LOG_VERSION;
1253
12541module.exports.createLogger = function createLogger(options) {
12551 return new Logger(options);
1256};
1257
12581module.exports.RingBuffer = RingBuffer;
1259
1260// Useful for custom `type == 'raw'` streams that may do JSON stringification
1261// of log records themselves. Usage:
1262// var str = JSON.stringify(rec, bunyan.safeCycles());
12631module.exports.safeCycles = safeCycles;
1264

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/admin.js

15%
116
18
98
LineHitsSource
1/*!
2 * Module dependencies.
3 */
41var Collection = require('./collection').Collection,
5 Cursor = require('./cursor').Cursor,
6 DbCommand = require('./commands/db_command').DbCommand,
7 utils = require('./utils');
8
9/**
10 * Allows the user to access the admin functionality of MongoDB
11 *
12 * @class Represents the Admin methods of MongoDB.
13 * @param {Object} db Current db instance we wish to perform Admin operations on.
14 * @return {Function} Constructor for Admin type.
15 */
161function Admin(db) {
170 if(!(this instanceof Admin)) return new Admin(db);
180 this.db = db;
19};
20
21/**
22 * Retrieve the server information for the current
23 * instance of the db client
24 *
25 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from buildInfo or null if an error occured.
26 * @return {null} Returns no result
27 * @api public
28 */
291Admin.prototype.buildInfo = function(callback) {
300 this.serverInfo(callback);
31}
32
33/**
34 * Retrieve the server information for the current
35 * instance of the db client
36 *
37 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverInfo or null if an error occured.
38 * @return {null} Returns no result
39 * @api private
40 */
411Admin.prototype.serverInfo = function(callback) {
420 this.db.executeDbAdminCommand({buildinfo:1}, function(err, doc) {
430 if(err != null) return callback(err, null);
440 return callback(null, doc.documents[0]);
45 });
46}
47
48/**
49 * Retrieve this db's server status.
50 *
51 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverStatus or null if an error occured.
52 * @return {null}
53 * @api public
54 */
551Admin.prototype.serverStatus = function(callback) {
560 var self = this;
57
580 this.db.executeDbAdminCommand({serverStatus: 1}, function(err, doc) {
590 if(err == null && doc.documents[0].ok === 1) {
600 callback(null, doc.documents[0]);
61 } else {
620 if(err) return callback(err, false);
630 return callback(utils.toError(doc.documents[0]), false);
64 }
65 });
66};
67
68/**
69 * Retrieve the current profiling Level for MongoDB
70 *
71 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingLevel or null if an error occured.
72 * @return {null} Returns no result
73 * @api public
74 */
751Admin.prototype.profilingLevel = function(callback) {
760 var self = this;
77
780 this.db.executeDbAdminCommand({profile:-1}, function(err, doc) {
790 doc = doc.documents[0];
80
810 if(err == null && doc.ok === 1) {
820 var was = doc.was;
830 if(was == 0) return callback(null, "off");
840 if(was == 1) return callback(null, "slow_only");
850 if(was == 2) return callback(null, "all");
860 return callback(new Error("Error: illegal profiling level value " + was), null);
87 } else {
880 err != null ? callback(err, null) : callback(new Error("Error with profile command"), null);
89 }
90 });
91};
92
93/**
94 * Ping the MongoDB server and retrieve results
95 *
96 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from ping or null if an error occured.
97 * @return {null} Returns no result
98 * @api public
99 */
1001Admin.prototype.ping = function(options, callback) {
101 // Unpack calls
1020 var args = Array.prototype.slice.call(arguments, 0);
1030 callback = args.pop();
104
1050 this.db.executeDbAdminCommand({ping: 1}, callback);
106}
107
108/**
109 * Authenticate against MongoDB
110 *
111 * @param {String} username The user name for the authentication.
112 * @param {String} password The password for the authentication.
113 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from authenticate or null if an error occured.
114 * @return {null} Returns no result
115 * @api public
116 */
1171Admin.prototype.authenticate = function(username, password, callback) {
1180 this.db.authenticate(username, password, {authdb: 'admin'}, function(err, doc) {
1190 return callback(err, doc);
120 })
121}
122
123/**
124 * Logout current authenticated user
125 *
126 * @param {Object} [options] Optional parameters to the command.
127 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from logout or null if an error occured.
128 * @return {null} Returns no result
129 * @api public
130 */
1311Admin.prototype.logout = function(callback) {
1320 this.db.logout({authdb: 'admin'}, function(err, doc) {
1330 return callback(err, doc);
134 })
135}
136
137/**
138 * Add a user to the MongoDB server, if the user exists it will
139 * overwrite the current password
140 *
141 * Options
142 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
143 *
144 * @param {String} username The user name for the authentication.
145 * @param {String} password The password for the authentication.
146 * @param {Object} [options] additional options during update.
147 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from addUser or null if an error occured.
148 * @return {null} Returns no result
149 * @api public
150 */
1511Admin.prototype.addUser = function(username, password, options, callback) {
1520 var args = Array.prototype.slice.call(arguments, 2);
1530 callback = args.pop();
1540 options = args.length ? args.shift() : {};
155 // Set the db name to admin
1560 options.dbName = 'admin';
157 // Add user
1580 this.db.addUser(username, password, options, function(err, doc) {
1590 return callback(err, doc);
160 })
161}
162
163/**
164 * Remove a user from the MongoDB server
165 *
166 * Options
167 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
168 *
169 * @param {String} username The user name for the authentication.
170 * @param {Object} [options] additional options during update.
171 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occured.
172 * @return {null} Returns no result
173 * @api public
174 */
1751Admin.prototype.removeUser = function(username, options, callback) {
1760 var self = this;
1770 var args = Array.prototype.slice.call(arguments, 1);
1780 callback = args.pop();
1790 options = args.length ? args.shift() : {};
1800 options.dbName = 'admin';
181
1820 this.db.removeUser(username, options, function(err, doc) {
1830 return callback(err, doc);
184 })
185}
186
187/**
188 * Set the current profiling level of MongoDB
189 *
190 * @param {String} level The new profiling level (off, slow_only, all)
191 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from setProfilingLevel or null if an error occured.
192 * @return {null} Returns no result
193 * @api public
194 */
1951Admin.prototype.setProfilingLevel = function(level, callback) {
1960 var self = this;
1970 var command = {};
1980 var profile = 0;
199
2000 if(level == "off") {
2010 profile = 0;
2020 } else if(level == "slow_only") {
2030 profile = 1;
2040 } else if(level == "all") {
2050 profile = 2;
206 } else {
2070 return callback(new Error("Error: illegal profiling level value " + level));
208 }
209
210 // Set up the profile number
2110 command['profile'] = profile;
212
2130 this.db.executeDbAdminCommand(command, function(err, doc) {
2140 doc = doc.documents[0];
215
2160 if(err == null && doc.ok === 1)
2170 return callback(null, level);
2180 return err != null ? callback(err, null) : callback(new Error("Error with profile command"), null);
219 });
220};
221
222/**
223 * Retrive the current profiling information for MongoDB
224 *
225 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingInfo or null if an error occured.
226 * @return {null} Returns no result
227 * @api public
228 */
2291Admin.prototype.profilingInfo = function(callback) {
2300 try {
2310 new Cursor(this.db, new Collection(this.db, DbCommand.SYSTEM_PROFILE_COLLECTION), {}, {}, {dbName: 'admin'}).toArray(function(err, items) {
2320 return callback(err, items);
233 });
234 } catch (err) {
2350 return callback(err, null);
236 }
237};
238
239/**
240 * Execute a db command against the Admin database
241 *
242 * @param {Object} command A command object `{ping:1}`.
243 * @param {Object} [options] Optional parameters to the command.
244 * @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter.
245 * @return {null} Returns no result
246 * @api public
247 */
2481Admin.prototype.command = function(command, options, callback) {
2490 var self = this;
2500 var args = Array.prototype.slice.call(arguments, 1);
2510 callback = args.pop();
2520 options = args.length ? args.shift() : {};
253
254 // Execute a command
2550 this.db.executeDbAdminCommand(command, options, function(err, doc) {
256 // Ensure change before event loop executes
2570 return callback != null ? callback(err, doc) : null;
258 });
259}
260
261/**
262 * Validate an existing collection
263 *
264 * @param {String} collectionName The name of the collection to validate.
265 * @param {Object} [options] Optional parameters to the command.
266 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from validateCollection or null if an error occured.
267 * @return {null} Returns no result
268 * @api public
269 */
2701Admin.prototype.validateCollection = function(collectionName, options, callback) {
2710 var args = Array.prototype.slice.call(arguments, 1);
2720 callback = args.pop();
2730 options = args.length ? args.shift() : {};
274
2750 var self = this;
2760 var command = {validate: collectionName};
2770 var keys = Object.keys(options);
278
279 // Decorate command with extra options
2800 for(var i = 0; i < keys.length; i++) {
2810 if(options.hasOwnProperty(keys[i])) {
2820 command[keys[i]] = options[keys[i]];
283 }
284 }
285
2860 this.db.executeDbCommand(command, function(err, doc) {
2870 if(err != null) return callback(err, null);
2880 doc = doc.documents[0];
289
2900 if(doc.ok === 0)
2910 return callback(new Error("Error with validate command"), null);
2920 if(doc.result != null && doc.result.constructor != String)
2930 return callback(new Error("Error with validation data"), null);
2940 if(doc.result != null && doc.result.match(/exception|corrupt/) != null)
2950 return callback(new Error("Error: invalid collection " + collectionName), null);
2960 if(doc.valid != null && !doc.valid)
2970 return callback(new Error("Error: invalid collection " + collectionName), null);
298
2990 return callback(null, doc);
300 });
301};
302
303/**
304 * List the available databases
305 *
306 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from listDatabases or null if an error occured.
307 * @return {null} Returns no result
308 * @api public
309 */
3101Admin.prototype.listDatabases = function(callback) {
311 // Execute the listAllDatabases command
3120 this.db.executeDbAdminCommand({listDatabases:1}, {}, function(err, doc) {
3130 if(err != null) return callback(err, null);
3140 return callback(null, doc.documents[0]);
315 });
316}
317
318/**
319 * Get ReplicaSet status
320 *
321 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from replSetGetStatus or null if an error occured.
322 * @return {null}
323 * @api public
324 */
3251Admin.prototype.replSetGetStatus = function(callback) {
3260 var self = this;
327
3280 this.db.executeDbAdminCommand({replSetGetStatus:1}, function(err, doc) {
3290 if(err == null && doc.documents[0].ok === 1)
3300 return callback(null, doc.documents[0]);
3310 if(err) return callback(err, false);
3320 return callback(utils.toError(doc.documents[0]), false);
333 });
334};
335
336/**
337 * @ignore
338 */
3391exports.Admin = Admin;
340

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/aggregation_cursor.js

6%
82
5
77
LineHitsSource
11var ReadPreference = require('./connection/read_preference').ReadPreference
2 , Readable = require('stream').Readable
3 , CommandCursor = require('./command_cursor').CommandCursor
4 , utils = require('./utils')
5 , shared = require('./collection/shared')
6 , inherits = require('util').inherits;
7
81var AggregationCursor = function(collection, serverCapabilities, options) {
90 var pipe = [];
100 var self = this;
110 var results = null;
120 var _cursor_options = {};
13 // Ensure we have options set up
140 options = options == null ? {} : options;
15
16 // If a pipeline was provided
170 pipe = Array.isArray(options.pipe) ? options.pipe : pipe;
18 // Set passed in batchSize if provided
190 if(typeof options.batchSize == 'number') _cursor_options.batchSize = options.batchSize;
20 // Get the read Preference
210 var readPreference = shared._getReadConcern(collection, options);
22
23 // Set up
240 Readable.call(this, {objectMode: true});
25
26 // Contains connection
270 var connection = null;
28
29 // Set the read preference
300 var _options = {
31 readPreference: readPreference
32 };
33
34 // Actual command
350 var command = {
36 aggregate: collection.collectionName
37 , pipeline: pipe
38 , cursor: _cursor_options
39 }
40
41 // If allowDiskUsage is set
420 if(typeof options.allowDiskUsage == 'boolean')
430 command.allowDiskUsage = options.allowDiskUsage;
44
45 // Command cursor (if we support one)
460 var commandCursor = new CommandCursor(collection.db, collection, command);
47
48 // // Internal cursor methods
49 // this.find = function(selector) {
50 // pipe.push({$match: selector});
51 // return self;
52 // }
53
54 // this.unwind = function(unwind) {
55 // pipe.push({$unwind: unwind});
56 // return self;
57 // }
58
59 // this.group = function(group) {
60 // pipe.push({$group: group});
61 // return self;
62 // }
63
64 // this.project = function(project) {
65 // pipe.push({$project: project});
66 // return self;
67 // }
68
69 // this.limit = function(limit) {
70 // pipe.push({$limit: limit});
71 // return self;
72 // }
73
74 // this.geoNear = function(geoNear) {
75 // pipe.push({$geoNear: geoNear});
76 // return self;
77 // }
78
79 // this.sort = function(sort) {
80 // pipe.push({$sort: sort});
81 // return self;
82 // }
83
84 // this.withReadPreference = function(read_preference) {
85 // _options.readPreference = read_preference;
86 // return self;
87 // }
88
89 // this.withQueryOptions = function(options) {
90 // if(options.batchSize) {
91 // _cursor_options.batchSize = options.batchSize;
92 // }
93
94 // // Return the cursor
95 // return self;
96 // }
97
98 // this.skip = function(skip) {
99 // pipe.push({$skip: skip});
100 // return self;
101 // }
102
103 // this.allowDiskUsage = function(allowDiskUsage) {
104 // command.allowDiskUsage = allowDiskUsage;
105 // return self;
106 // }
107
1080 this.explain = function(callback) {
1090 if(typeof callback != 'function')
1100 throw utils.toError("AggregationCursor explain requires a callback function");
111
112 // Add explain options
1130 _options.explain = true;
114 // Execute aggregation pipeline
1150 collection.aggregate(pipe, _options, function(err, results) {
1160 if(err) return callback(err, null);
1170 callback(null, results);
118 });
119 }
120
121 // this.maxTimeMS = function(maxTimeMS) {
122 // if(typeof maxTimeMS != 'number') {
123 // throw new Error("maxTimeMS must be a number");
124 // }
125
126 // // Save the maxTimeMS
127 // _options.maxTimeMS = maxTimeMS
128 // // Set the maxTimeMS on the command cursor
129 // commandCursor.maxTimeMS(maxTimeMS);
130 // return self;
131 // }
132
1330 this.get = function(callback) {
1340 if(typeof callback != 'function')
1350 throw utils.toError("AggregationCursor get requires a callback function");
136 // Checkout a connection
1370 var _connection = collection.db.serverConfig.checkoutReader(_options.readPreference);
138 // Fall back
1390 if(!_connection.serverCapabilities.hasAggregationCursor) {
1400 return collection.aggregate(pipe, _options, function(err, results) {
1410 if(err) return callback(err);
1420 callback(null, results);
143 });
144 }
145
146 // Execute get using command Cursor
1470 commandCursor.get({connection: _connection}, callback);
148 }
149
1500 this.getOne = function(callback) {
1510 if(typeof callback != 'function')
1520 throw utils.toError("AggregationCursor getOne requires a callback function");
153 // Set the limit to 1
1540 pipe.push({$limit: 1});
155 // For now we have no cursor command so let's just wrap existing results
1560 collection.aggregate(pipe, _options, function(err, results) {
1570 if(err) return callback(err);
1580 callback(null, results[0]);
159 });
160 }
161
1620 this.each = function(callback) {
163 // Checkout a connection if we have none
1640 if(!connection)
1650 connection = collection.db.serverConfig.checkoutReader(_options.readPreference);
166
167 // Fall back
1680 if(!connection.serverCapabilities.hasAggregationCursor) {
1690 collection.aggregate(pipe, _options, function(err, _results) {
1700 if(err) return callback(err);
171
1720 while(_results.length > 0) {
1730 callback(null, _results.shift());
174 }
175
1760 callback(null, null);
177 });
178 }
179
180 // Execute each using command Cursor
1810 commandCursor.each({connection: connection}, callback);
182 }
183
1840 this.next = function(callback) {
1850 if(typeof callback != 'function')
1860 throw utils.toError("AggregationCursor next requires a callback function");
187
188 // Checkout a connection if we have none
1890 if(!connection)
1900 connection = collection.db.serverConfig.checkoutReader(_options.readPreference);
191
192 // Fall back
1930 if(!connection.serverCapabilities.hasAggregationCursor) {
1940 if(!results) {
195 // For now we have no cursor command so let's just wrap existing results
1960 return collection.aggregate(pipe, _options, function(err, _results) {
1970 if(err) return callback(err);
1980 results = _results;
199
200 // Ensure we don't issue undefined
2010 var item = results.shift();
2020 callback(null, item ? item : null);
203 });
204 }
205
206 // Ensure we don't issue undefined
2070 var item = results.shift();
208 // Return the item
2090 return callback(null, item ? item : null);
210 }
211
212 // Execute next using command Cursor
2130 commandCursor.next({connection: connection}, callback);
214 }
215
216 //
217 // Close method
218 //
2190 this.close = function(callback) {
2200 if(typeof callback != 'function')
2210 throw utils.toError("AggregationCursor close requires a callback function");
222
223 // Checkout a connection if we have none
2240 if(!connection)
2250 connection = collection.db.serverConfig.checkoutReader(_options.readPreference);
226
227 // Fall back
2280 if(!connection.serverCapabilities.hasAggregationCursor) {
2290 return callback(null, null);
230 }
231
232 // Execute next using command Cursor
2330 commandCursor.close({connection: connection}, callback);
234 }
235
236 //
237 // Stream method
238 //
2390 this._read = function(n) {
2400 self.next(function(err, result) {
2410 if(err) {
2420 self.emit('error', err);
2430 return self.push(null);
244 }
245
2460 self.push(result);
247 });
248 }
249}
250
251// Inherit from Readable
2521if(Readable != null) {
2531 inherits(AggregationCursor, Readable);
254}
255
256// Exports the Aggregation Framework
2571exports.AggregationCursor = AggregationCursor;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js

12%
25
3
22
LineHitsSource
11var DbCommand = require('../commands/db_command').DbCommand
2 , utils = require('../utils');
3
41var authenticate = function(db, username, password, authdb, options, callback) {
50 var numberOfConnections = 0;
60 var errorObject = null;
7
80 if(options['connection'] != null) {
9 //if a connection was explicitly passed on options, then we have only one...
100 numberOfConnections = 1;
11 } else {
12 // Get the amount of connections in the pool to ensure we have authenticated all comments
130 numberOfConnections = db.serverConfig.allRawConnections().length;
140 options['onAll'] = true;
15 }
16
17 // Execute all four
180 db._executeQueryCommand(DbCommand.createGetNonceCommand(db), options, function(err, result, connection) {
19 // console.log("--------------------------------------------- MONGODB-CR 0")
20 // console.dir(err)
21 // Execute on all the connections
220 if(err == null) {
23 // Nonce used to make authentication request with md5 hash
240 var nonce = result.documents[0].nonce;
25 // Execute command
260 db._executeQueryCommand(DbCommand.createAuthenticationCommand(db, username, password, nonce, authdb), {connection:connection}, function(err, result) {
27 // console.log("--------------------------------------------- MONGODB-CR 1")
28 // console.dir(err)
29 // console.dir(result)
30 // Count down
310 numberOfConnections = numberOfConnections - 1;
32 // Ensure we save any error
330 if(err) {
340 errorObject = err;
350 } else if(result
36 && Array.isArray(result.documents)
37 && result.documents.length > 0
38 && (result.documents[0].err != null || result.documents[0].errmsg != null)) {
390 errorObject = utils.toError(result.documents[0]);
40 }
41
42 // Work around the case where the number of connections are 0
430 if(numberOfConnections <= 0 && typeof callback == 'function') {
440 var internalCallback = callback;
450 callback = null;
46
470 if(errorObject == null
48 && result && Array.isArray(result.documents) && result.documents.length > 0
49 && result.documents[0].ok == 1) { // We authenticated correctly save the credentials
500 db.serverConfig.auth.add('MONGODB-CR', db.databaseName, username, password, authdb);
51 // Return callback
520 internalCallback(errorObject, true);
53 } else {
540 internalCallback(errorObject, false);
55 }
56 }
57 });
58 }
59 });
60}
61
621exports.authenticate = authenticate;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js

21%
57
12
45
LineHitsSource
11var DbCommand = require('../commands/db_command').DbCommand
2 , utils = require('../utils')
3 , format = require('util').format;
4
5// Kerberos class
61var Kerberos = null;
71var MongoAuthProcess = null;
8// Try to grab the Kerberos class
91try {
101 Kerberos = require('kerberos').Kerberos
11 // Authentication process for Mongo
121 MongoAuthProcess = require('kerberos').processes.MongoAuthProcess
13} catch(err) {}
14
151var authenticate = function(db, username, password, authdb, options, callback) {
160 var numberOfConnections = 0;
170 var errorObject = null;
18 // We don't have the Kerberos library
190 if(Kerberos == null) return callback(new Error("Kerberos library is not installed"));
20
210 if(options['connection'] != null) {
22 //if a connection was explicitly passed on options, then we have only one...
230 numberOfConnections = 1;
24 } else {
25 // Get the amount of connections in the pool to ensure we have authenticated all comments
260 numberOfConnections = db.serverConfig.allRawConnections().length;
270 options['onAll'] = true;
28 }
29
30 // Grab all the connections
310 var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections();
320 var gssapiServiceName = options['gssapiServiceName'] || 'mongodb';
330 var error = null;
34 // Authenticate all connections
350 for(var i = 0; i < numberOfConnections; i++) {
36
37 // Start Auth process for a connection
380 GSSAPIInitialize(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) {
39 // Adjust number of connections left to connect
400 numberOfConnections = numberOfConnections - 1;
41 // If we have an error save it
420 if(err) error = err;
43
44 // We are done
450 if(numberOfConnections == 0) {
460 if(err) return callback(error, false);
47 // We authenticated correctly save the credentials
480 db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName);
49 // Return valid callback
500 return callback(null, true);
51 }
52 });
53 }
54}
55
56//
57// Initialize step
581var GSSAPIInitialize = function(db, username, password, authdb, gssapiServiceName, connection, callback) {
59 // Create authenticator
600 var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, gssapiServiceName);
61
62 // Perform initialization
630 mongo_auth_process.init(username, password, function(err, context) {
640 if(err) return callback(err, false);
65
66 // Perform the first step
670 mongo_auth_process.transition('', function(err, payload) {
680 if(err) return callback(err, false);
69
70 // Call the next db step
710 MongoDBGSSAPIFirstStep(mongo_auth_process, payload, db, username, password, authdb, connection, callback);
72 });
73 });
74}
75
76//
77// Perform first step against mongodb
781var MongoDBGSSAPIFirstStep = function(mongo_auth_process, payload, db, username, password, authdb, connection, callback) {
79 // Build the sasl start command
800 var command = {
81 saslStart: 1
82 , mechanism: 'GSSAPI'
83 , payload: payload
84 , autoAuthorize: 1
85 };
86
87 // Execute first sasl step
880 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
890 if(err) return callback(err, false);
90 // Get the payload
910 doc = doc.documents[0];
920 var db_payload = doc.payload;
93
940 mongo_auth_process.transition(doc.payload, function(err, payload) {
950 if(err) return callback(err, false);
96
97 // MongoDB API Second Step
980 MongoDBGSSAPISecondStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback);
99 });
100 });
101}
102
103//
104// Perform first step against mongodb
1051var MongoDBGSSAPISecondStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) {
106 // Build Authentication command to send to MongoDB
1070 var command = {
108 saslContinue: 1
109 , conversationId: doc.conversationId
110 , payload: payload
111 };
112
113 // Execute the command
1140 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
1150 if(err) return callback(err, false);
116
117 // Get the result document
1180 doc = doc.documents[0];
119
120 // Call next transition for kerberos
1210 mongo_auth_process.transition(doc.payload, function(err, payload) {
1220 if(err) return callback(err, false);
123
124 // Call the last and third step
1250 MongoDBGSSAPIThirdStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback);
126 });
127 });
128}
129
1301var MongoDBGSSAPIThirdStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) {
131 // Build final command
1320 var command = {
133 saslContinue: 1
134 , conversationId: doc.conversationId
135 , payload: payload
136 };
137
138 // Let's finish the auth process against mongodb
1390 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
1400 if(err) return callback(err, false);
141
1420 mongo_auth_process.transition(null, function(err, payload) {
1430 if(err) return callback(err, false);
1440 callback(null, true);
145 });
146 });
147}
148
1491exports.authenticate = authenticate;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js

11%
27
3
24
LineHitsSource
11var DbCommand = require('../commands/db_command').DbCommand
2 , utils = require('../utils')
3 , Binary = require('bson').Binary
4 , format = require('util').format;
5
61var authenticate = function(db, username, password, options, callback) {
70 var numberOfConnections = 0;
80 var errorObject = null;
9
100 if(options['connection'] != null) {
11 //if a connection was explicitly passed on options, then we have only one...
120 numberOfConnections = 1;
13 } else {
14 // Get the amount of connections in the pool to ensure we have authenticated all comments
150 numberOfConnections = db.serverConfig.allRawConnections().length;
160 options['onAll'] = true;
17 }
18
19 // Create payload
200 var payload = new Binary(format("\x00%s\x00%s", username, password));
21
22 // Let's start the sasl process
230 var command = {
24 saslStart: 1
25 , mechanism: 'PLAIN'
26 , payload: payload
27 , autoAuthorize: 1
28 };
29
30 // Grab all the connections
310 var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections();
32
33 // Authenticate all connections
340 for(var i = 0; i < numberOfConnections; i++) {
350 var connection = connections[i];
36 // Execute first sasl step
370 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, result) {
38 // Count down
390 numberOfConnections = numberOfConnections - 1;
40
41 // Ensure we save any error
420 if(err) {
430 errorObject = err;
440 } else if(result.documents[0].err != null || result.documents[0].errmsg != null){
450 errorObject = utils.toError(result.documents[0]);
46 }
47
48 // Work around the case where the number of connections are 0
490 if(numberOfConnections <= 0 && typeof callback == 'function') {
500 var internalCallback = callback;
510 callback = null;
52
530 if(errorObject == null && result.documents[0].ok == 1) {
54 // We authenticated correctly save the credentials
550 db.serverConfig.auth.add('PLAIN', db.databaseName, username, password);
56 // Return callback
570 internalCallback(errorObject, true);
58 } else {
590 internalCallback(errorObject, false);
60 }
61 }
62 });
63 }
64}
65
661exports.authenticate = authenticate;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js

16%
53
9
44
LineHitsSource
11var DbCommand = require('../commands/db_command').DbCommand
2 , utils = require('../utils')
3 , format = require('util').format;
4
5// Kerberos class
61var Kerberos = null;
71var MongoAuthProcess = null;
8// Try to grab the Kerberos class
91try {
101 Kerberos = require('kerberos').Kerberos
11 // Authentication process for Mongo
121 MongoAuthProcess = require('kerberos').processes.MongoAuthProcess
13} catch(err) {}
14
151var authenticate = function(db, username, password, authdb, options, callback) {
160 var numberOfConnections = 0;
170 var errorObject = null;
18 // We don't have the Kerberos library
190 if(Kerberos == null) return callback(new Error("Kerberos library is not installed"));
20
210 if(options['connection'] != null) {
22 //if a connection was explicitly passed on options, then we have only one...
230 numberOfConnections = 1;
24 } else {
25 // Get the amount of connections in the pool to ensure we have authenticated all comments
260 numberOfConnections = db.serverConfig.allRawConnections().length;
270 options['onAll'] = true;
28 }
29
30 // Set the sspi server name
310 var gssapiServiceName = options['gssapiServiceName'] || 'mongodb';
32
33 // Grab all the connections
340 var connections = db.serverConfig.allRawConnections();
350 var error = null;
36
37 // Authenticate all connections
380 for(var i = 0; i < numberOfConnections; i++) {
39 // Start Auth process for a connection
400 SSIPAuthenticate(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) {
41 // Adjust number of connections left to connect
420 numberOfConnections = numberOfConnections - 1;
43 // If we have an error save it
440 if(err) error = err;
45
46 // We are done
470 if(numberOfConnections == 0) {
480 if(err) return callback(err, false);
49 // We authenticated correctly save the credentials
500 db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName);
51 // Return valid callback
520 return callback(null, true);
53 }
54 });
55 }
56}
57
581var SSIPAuthenticate = function(db, username, password, authdb, service_name, connection, callback) {
59 // --------------------------------------------------------------
60 // Async Version
61 // --------------------------------------------------------------
620 var command = {
63 saslStart: 1
64 , mechanism: 'GSSAPI'
65 , payload: ''
66 , autoAuthorize: 1
67 };
68
69 // Create authenticator
700 var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, service_name);
71
72 // Execute first sasl step
730 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
740 if(err) return callback(err);
750 doc = doc.documents[0];
76
770 mongo_auth_process.init(username, password, function(err) {
780 if(err) return callback(err);
79
800 mongo_auth_process.transition(doc.payload, function(err, payload) {
810 if(err) return callback(err);
82
83 // Perform the next step against mongod
840 var command = {
85 saslContinue: 1
86 , conversationId: doc.conversationId
87 , payload: payload
88 };
89
90 // Execute the command
910 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
920 if(err) return callback(err);
930 doc = doc.documents[0];
94
950 mongo_auth_process.transition(doc.payload, function(err, payload) {
960 if(err) return callback(err);
97
98 // Perform the next step against mongod
990 var command = {
100 saslContinue: 1
101 , conversationId: doc.conversationId
102 , payload: payload
103 };
104
105 // Execute the command
1060 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
1070 if(err) return callback(err);
1080 doc = doc.documents[0];
109
1100 mongo_auth_process.transition(doc.payload, function(err, payload) {
111 // Perform the next step against mongod
1120 var command = {
113 saslContinue: 1
114 , conversationId: doc.conversationId
115 , payload: payload
116 };
117
118 // Execute the command
1190 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
1200 if(err) return callback(err);
1210 doc = doc.documents[0];
122
1230 if(doc.done) return callback(null, true);
1240 callback(new Error("Authentication failed"), false);
125 });
126 });
127 });
128 });
129 });
130 });
131 });
132 });
133}
134
1351exports.authenticate = authenticate;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/auth/mongodb_x509.js

11%
26
3
23
LineHitsSource
11var DbCommand = require('../commands/db_command').DbCommand
2 , utils = require('../utils')
3 , Binary = require('bson').Binary
4 , format = require('util').format;
5
61var authenticate = function(db, username, password, options, callback) {
70 var numberOfConnections = 0;
80 var errorObject = null;
9
100 if(options['connection'] != null) {
11 //if a connection was explicitly passed on options, then we have only one...
120 numberOfConnections = 1;
13 } else {
14 // Get the amount of connections in the pool to ensure we have authenticated all comments
150 numberOfConnections = db.serverConfig.allRawConnections().length;
160 options['onAll'] = true;
17 }
18
19 // Let's start the sasl process
200 var command = {
21 authenticate: 1
22 , mechanism: 'MONGODB-X509'
23 , user: username
24 };
25
26 // Grab all the connections
270 var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections();
28
29 // Authenticate all connections
300 for(var i = 0; i < numberOfConnections; i++) {
310 var connection = connections[i];
32 // Execute first sasl step
330 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, result) {
34 // Count down
350 numberOfConnections = numberOfConnections - 1;
36
37 // Ensure we save any error
380 if(err) {
390 errorObject = err;
400 } else if(result.documents[0].err != null || result.documents[0].errmsg != null){
410 errorObject = utils.toError(result.documents[0]);
42 }
43
44 // Work around the case where the number of connections are 0
450 if(numberOfConnections <= 0 && typeof callback == 'function') {
460 var internalCallback = callback;
470 callback = null;
48
490 if(errorObject == null && result.documents[0].ok == 1) {
50 // We authenticated correctly save the credentials
510 db.serverConfig.auth.add('MONGODB-X509', db.databaseName, username, password);
52 // Return callback
530 internalCallback(errorObject, true);
54 } else {
550 internalCallback(errorObject, false);
56 }
57 }
58 });
59 }
60}
61
621exports.authenticate = authenticate;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/collection.js

63%
52
33
19
LineHitsSource
1/**
2 * Module dependencies.
3 * @ignore
4 */
51var InsertCommand = require('./commands/insert_command').InsertCommand
6 , QueryCommand = require('./commands/query_command').QueryCommand
7 , DeleteCommand = require('./commands/delete_command').DeleteCommand
8 , UpdateCommand = require('./commands/update_command').UpdateCommand
9 , DbCommand = require('./commands/db_command').DbCommand
10 , ObjectID = require('bson').ObjectID
11 , Code = require('bson').Code
12 , Cursor = require('./cursor').Cursor
13 , utils = require('./utils')
14 , shared = require('./collection/shared')
15 , core = require('./collection/core')
16 , query = require('./collection/query')
17 , index = require('./collection/index')
18 , geo = require('./collection/geo')
19 , commands = require('./collection/commands')
20 , aggregation = require('./collection/aggregation');
21
22/**
23 * Create a new Collection instance (INTERNAL TYPE, do not instantiate directly)
24 *
25 * Options
26 * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
27 * - **slaveOk** {Boolean, default:false}, Allow reads from secondaries.
28 * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
29 * - **raw** {Boolean, default:false}, perform all operations using raw bson objects.
30 * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
31 *
32 * @class Represents a Collection
33 * @param {Object} db db instance.
34 * @param {String} collectionName collection name.
35 * @param {Object} [pkFactory] alternative primary key factory.
36 * @param {Object} [options] additional options for the collection.
37 * @return {Object} a collection instance.
38 */
391function Collection (db, collectionName, pkFactory, options) {
400 if(!(this instanceof Collection)) return new Collection(db, collectionName, pkFactory, options);
41
420 shared.checkCollectionName(collectionName);
43
440 this.db = db;
450 this.collectionName = collectionName;
460 this.internalHint = null;
470 this.opts = options != null && ('object' === typeof options) ? options : {};
480 this.slaveOk = options == null || options.slaveOk == null ? db.slaveOk : options.slaveOk;
490 this.serializeFunctions = options == null || options.serializeFunctions == null ? db.serializeFunctions : options.serializeFunctions;
500 this.raw = options == null || options.raw == null ? db.raw : options.raw;
51
520 this.readPreference = options == null || options.readPreference == null ? db.serverConfig.options.readPreference : options.readPreference;
530 this.readPreference = this.readPreference == null ? 'primary' : this.readPreference;
54
55
560 this.pkFactory = pkFactory == null
57 ? ObjectID
58 : pkFactory;
59
60 // Server Capabilities
610 this.serverCapabilities = this.db.serverConfig._serverCapabilities;
62}
63
64/**
65 * Inserts a single document or a an array of documents into MongoDB.
66 *
67 * Options
68 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
69 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
70 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
71 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
72 * - **continueOnError/keepGoing** {Boolean, default:false}, keep inserting documents even if one document has an error, *mongodb 1.9.1 >*.
73 * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
74 * - **forceServerObjectId** {Boolean, default:false}, let server assign ObjectId instead of the driver
75 * - **checkKeys** {Boolean, default:true}, allows for disabling of document key checking (WARNING OPENS YOU UP TO INJECTION ATTACKS)
76 *
77 * Deprecated Options
78 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
79 *
80 * @param {Array|Object} docs
81 * @param {Object} [options] optional options for insert command
82 * @param {Function} [callback] optional callback for the function, must be provided when using a writeconcern
83 * @return {null}
84 * @api public
85 */
862Collection.prototype.insert = function() { return core.insert; }();
87
88/**
89 * Removes documents specified by `selector` from the db.
90 *
91 * Options
92 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
93 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
94 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
95 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
96 * - **single** {Boolean, default:false}, removes the first document found.
97 *
98 * Deprecated Options
99 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
100 *
101 * @param {Object} [selector] optional select, no selector is equivalent to removing all documents.
102 * @param {Object} [options] additional options during remove.
103 * @param {Function} [callback] must be provided if you performing a remove with a writeconcern
104 * @return {null}
105 * @api public
106 */
1072Collection.prototype.remove = function() { return core.remove; }();
108
109/**
110 * Renames the collection.
111 *
112 * Options
113 * - **dropTarget** {Boolean, default:false}, drop the target name collection if it previously exists.
114 *
115 * @param {String} newName the new name of the collection.
116 * @param {Object} [options] returns option results.
117 * @param {Function} callback the callback accepting the result
118 * @return {null}
119 * @api public
120 */
1212Collection.prototype.rename = function() { return commands.rename; }();
122
123/**
124 * Save a document. Simple full document replacement function. Not recommended for efficiency, use atomic
125 * operators and update instead for more efficient operations.
126 *
127 * Options
128 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
129 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
130 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
131 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
132 *
133 * Deprecated Options
134 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
135 *
136 * @param {Object} [doc] the document to save
137 * @param {Object} [options] additional options during remove.
138 * @param {Function} [callback] must be provided if you performing a safe save
139 * @return {null}
140 * @api public
141 */
1422Collection.prototype.save = function() { return core.save; }();
143
144/**
145 * Updates documents.
146 *
147 * Options
148 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
149 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
150 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
151 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
152 * - **upsert** {Boolean, default:false}, perform an upsert operation.
153 * - **multi** {Boolean, default:false}, update all documents matching the selector.
154 * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
155 * - **checkKeys** {Boolean, default:true}, allows for disabling of document key checking (WARNING OPENS YOU UP TO INJECTION ATTACKS)
156 *
157 * Deprecated Options
158 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
159 *
160 * @param {Object} selector the query to select the document/documents to be updated
161 * @param {Object} document the fields/vals to be updated, or in the case of an upsert operation, inserted.
162 * @param {Object} [options] additional options during update.
163 * @param {Function} [callback] must be provided if you performing an update with a writeconcern
164 * @return {null}
165 * @api public
166 */
1672Collection.prototype.update = function() { return core.update; }();
168
169/**
170 * The distinct command returns returns a list of distinct values for the given key across a collection.
171 *
172 * Options
173 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
174 *
175 * @param {String} key key to run distinct against.
176 * @param {Object} [query] option query to narrow the returned objects.
177 * @param {Object} [options] additional options during update.
178 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from distinct or null if an error occured.
179 * @return {null}
180 * @api public
181 */
1822Collection.prototype.distinct = function() { return commands.distinct; }();
183
184/**
185 * Count number of matching documents in the db to a query.
186 *
187 * Options
188 * - **skip** {Number}, The number of documents to skip for the count.
189 * - **limit** {Number}, The limit of documents to count.
190 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
191 *
192 * @param {Object} [query] query to filter by before performing count.
193 * @param {Object} [options] additional options during count.
194 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the count method or null if an error occured.
195 * @return {null}
196 * @api public
197 */
1982Collection.prototype.count = function() { return commands.count; }();
199
200/**
201 * Drop the collection
202 *
203 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the drop method or null if an error occured.
204 * @return {null}
205 * @api public
206 */
2071Collection.prototype.drop = function drop(callback) {
2080 this.db.dropCollection(this.collectionName, callback);
209};
210
211/**
212 * Find and update a document.
213 *
214 * Options
215 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
216 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
217 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
218 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
219 * - **remove** {Boolean, default:false}, set to true to remove the object before returning.
220 * - **upsert** {Boolean, default:false}, perform an upsert operation.
221 * - **new** {Boolean, default:false}, set to true if you want to return the modified object rather than the original. Ignored for remove.
222 *
223 * Deprecated Options
224 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
225 *
226 * @param {Object} query query object to locate the object to modify
227 * @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate
228 * @param {Object} doc - the fields/vals to be updated
229 * @param {Object} [options] additional options during update.
230 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndModify method or null if an error occured.
231 * @return {null}
232 * @api public
233 */
2342Collection.prototype.findAndModify = function() { return core.findAndModify; }();
235
236/**
237 * Find and remove a document
238 *
239 * Options
240 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
241 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
242 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
243 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
244 *
245 * Deprecated Options
246 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
247 *
248 * @param {Object} query query object to locate the object to modify
249 * @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate
250 * @param {Object} [options] additional options during update.
251 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndRemove method or null if an error occured.
252 * @return {null}
253 * @api public
254 */
2552Collection.prototype.findAndRemove = function() { return core.findAndRemove; }();
256
257/**
258 * Creates a cursor for a query that can be used to iterate over results from MongoDB
259 *
260 * Various argument possibilities
261 * - callback?
262 * - selector, callback?,
263 * - selector, fields, callback?
264 * - selector, options, callback?
265 * - selector, fields, options, callback?
266 * - selector, fields, skip, limit, callback?
267 * - selector, fields, skip, limit, timeout, callback?
268 *
269 * Options
270 * - **limit** {Number, default:0}, sets the limit of documents returned in the query.
271 * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc.
272 * - **fields** {Object}, the fields to return in the query. Object of fields to include or exclude (not both), {'a':1}
273 * - **skip** {Number, default:0}, set to skip N documents ahead in your query (useful for pagination).
274 * - **hint** {Object}, tell the query to use specific indexes in the query. Object of indexes to use, {'_id':1}
275 * - **explain** {Boolean, default:false}, explain the query instead of returning the data.
276 * - **snapshot** {Boolean, default:false}, snapshot query.
277 * - **timeout** {Boolean, default:false}, specify if the cursor can timeout.
278 * - **tailable** {Boolean, default:false}, specify if the cursor is tailable.
279 * - **tailableRetryInterval** {Number, default:100}, specify the miliseconds between getMores on tailable cursor.
280 * - **numberOfRetries** {Number, default:5}, specify the number of times to retry the tailable cursor.
281 * - **awaitdata** {Boolean, default:false} allow the cursor to wait for data, only applicable for tailable cursor.
282 * - **oplogReplay** {Boolean, default:false} sets an internal flag, only applicable for tailable cursor.
283 * - **exhaust** {Boolean, default:false} have the server send all the documents at once as getMore packets, not recommended.
284 * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results.
285 * - **returnKey** {Boolean, default:false}, only return the index key.
286 * - **maxScan** {Number}, Limit the number of items to scan.
287 * - **min** {Number}, Set index bounds.
288 * - **max** {Number}, Set index bounds.
289 * - **showDiskLoc** {Boolean, default:false}, Show disk location of results.
290 * - **comment** {String}, You can put a $comment field on a query to make looking in the profiler logs simpler.
291 * - **raw** {Boolean, default:false}, Return all BSON documents as Raw Buffer documents.
292 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
293 * - **numberOfRetries** {Number, default:5}, if using awaidata specifies the number of times to retry on timeout.
294 * - **partial** {Boolean, default:false}, specify if the cursor should return partial results when querying against a sharded system
295 *
296 * @param {Object|ObjectID} query query object to locate the object to modify
297 * @param {Object} [options] additional options during update.
298 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the find method or null if an error occured.
299 * @return {Cursor} returns a cursor to the query
300 * @api public
301 */
3022Collection.prototype.find = function() { return query.find; }();
303
304/**
305 * Finds a single document based on the query
306 *
307 * Various argument possibilities
308 * - callback?
309 * - selector, callback?,
310 * - selector, fields, callback?
311 * - selector, options, callback?
312 * - selector, fields, options, callback?
313 * - selector, fields, skip, limit, callback?
314 * - selector, fields, skip, limit, timeout, callback?
315 *
316 * Options
317 * - **limit** {Number, default:0}, sets the limit of documents returned in the query.
318 * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc.
319 * - **fields** {Object}, the fields to return in the query. Object of fields to include or exclude (not both), {'a':1}
320 * - **skip** {Number, default:0}, set to skip N documents ahead in your query (useful for pagination).
321 * - **hint** {Object}, tell the query to use specific indexes in the query. Object of indexes to use, {'_id':1}
322 * - **explain** {Boolean, default:false}, explain the query instead of returning the data.
323 * - **snapshot** {Boolean, default:false}, snapshot query.
324 * - **timeout** {Boolean, default:false}, specify if the cursor can timeout.
325 * - **tailable** {Boolean, default:false}, specify if the cursor is tailable.
326 * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results.
327 * - **returnKey** {Boolean, default:false}, only return the index key.
328 * - **maxScan** {Number}, Limit the number of items to scan.
329 * - **min** {Number}, Set index bounds.
330 * - **max** {Number}, Set index bounds.
331 * - **showDiskLoc** {Boolean, default:false}, Show disk location of results.
332 * - **comment** {String}, You can put a $comment field on a query to make looking in the profiler logs simpler.
333 * - **raw** {Boolean, default:false}, Return all BSON documents as Raw Buffer documents.
334 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
335 * - **partial** {Boolean, default:false}, specify if the cursor should return partial results when querying against a sharded system
336 *
337 * @param {Object|ObjectID} query query object to locate the object to modify
338 * @param {Object} [options] additional options during update.
339 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findOne method or null if an error occured.
340 * @return {Cursor} returns a cursor to the query
341 * @api public
342 */
3432Collection.prototype.findOne = function() { return query.findOne; }();
344
345/**
346 * Creates an index on the collection.
347 *
348 * Options
349 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
350 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
351 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
352 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
353 * - **unique** {Boolean, default:false}, creates an unique index.
354 * - **sparse** {Boolean, default:false}, creates a sparse index.
355 * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible.
356 * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value
357 * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates.
358 * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates.
359 * - **v** {Number}, specify the format version of the indexes.
360 * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
361 * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
362 *
363 * Deprecated Options
364 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
365 *
366 * @param {Object} fieldOrSpec fieldOrSpec that defines the index.
367 * @param {Object} [options] additional options during update.
368 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the createIndex method or null if an error occured.
369 * @return {null}
370 * @api public
371 */
3722Collection.prototype.createIndex = function() { return index.createIndex; }();
373
374/**
375 * Ensures that an index exists, if it does not it creates it
376 *
377 * Options
378 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
379 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
380 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
381 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
382 * - **unique** {Boolean, default:false}, creates an unique index.
383 * - **sparse** {Boolean, default:false}, creates a sparse index.
384 * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible.
385 * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value
386 * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates.
387 * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates.
388 * - **v** {Number}, specify the format version of the indexes.
389 * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
390 * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
391 *
392 * Deprecated Options
393 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
394 *
395 * @param {Object} fieldOrSpec fieldOrSpec that defines the index.
396 * @param {Object} [options] additional options during update.
397 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the ensureIndex method or null if an error occured.
398 * @return {null}
399 * @api public
400 */
4012Collection.prototype.ensureIndex = function() { return index.ensureIndex; }();
402
403/**
404 * Retrieves this collections index info.
405 *
406 * Options
407 * - **full** {Boolean, default:false}, returns the full raw index information.
408 *
409 * @param {Object} [options] additional options during update.
410 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexInformation method or null if an error occured.
411 * @return {null}
412 * @api public
413 */
4142Collection.prototype.indexInformation = function() { return index.indexInformation; }();
415
416/**
417 * Drops an index from this collection.
418 *
419 * @param {String} name
420 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndex method or null if an error occured.
421 * @return {null}
422 * @api public
423 */
4241Collection.prototype.dropIndex = function dropIndex (name, callback) {
4250 this.db.dropIndex(this.collectionName, name, callback);
426};
427
428/**
429 * Drops all indexes from this collection.
430 *
431 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropAllIndexes method or null if an error occured.
432 * @return {null}
433 * @api public
434 */
4352Collection.prototype.dropAllIndexes = function() { return index.dropAllIndexes; }();
436
437/**
438 * Drops all indexes from this collection.
439 *
440 * @deprecated
441 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndexes method or null if an error occured.
442 * @return {null}
443 * @api private
444 */
4452Collection.prototype.dropIndexes = function() { return Collection.prototype.dropAllIndexes; }();
446
447/**
448 * Reindex all indexes on the collection
449 * Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections.
450 *
451 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the reIndex method or null if an error occured.
452 * @return {null}
453 * @api public
454**/
4551Collection.prototype.reIndex = function(callback) {
4560 this.db.reIndex(this.collectionName, callback);
457}
458
459/**
460 * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection.
461 *
462 * Options
463 * - **out** {Object}, sets the output target for the map reduce job. *{inline:1} | {replace:'collectionName'} | {merge:'collectionName'} | {reduce:'collectionName'}*
464 * - **query** {Object}, query filter object.
465 * - **sort** {Object}, sorts the input objects using this key. Useful for optimization, like sorting by the emit key for fewer reduces.
466 * - **limit** {Number}, number of objects to return from collection.
467 * - **keeptemp** {Boolean, default:false}, keep temporary data.
468 * - **finalize** {Function | String}, finalize function.
469 * - **scope** {Object}, can pass in variables that can be access from map/reduce/finalize.
470 * - **jsMode** {Boolean, default:false}, it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X.
471 * - **verbose** {Boolean, default:false}, provide statistics on job execution time.
472 * - **readPreference** {String, only for inline results}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
473 *
474 * @param {Function|String} map the mapping function.
475 * @param {Function|String} reduce the reduce function.
476 * @param {Objects} [options] options for the map reduce job.
477 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the mapReduce method or null if an error occured.
478 * @return {null}
479 * @api public
480 */
4812Collection.prototype.mapReduce = function() { return aggregation.mapReduce; }();
482
483/**
484 * Run a group command across a collection
485 *
486 * Options
487 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
488 *
489 * @param {Object|Array|Function|Code} keys an object, array or function expressing the keys to group by.
490 * @param {Object} condition an optional condition that must be true for a row to be considered.
491 * @param {Object} initial initial value of the aggregation counter object.
492 * @param {Function|Code} reduce the reduce function aggregates (reduces) the objects iterated
493 * @param {Function|Code} finalize an optional function to be run on each item in the result set just before the item is returned.
494 * @param {Boolean} command specify if you wish to run using the internal group command or using eval, default is true.
495 * @param {Object} [options] additional options during update.
496 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the group method or null if an error occured.
497 * @return {null}
498 * @api public
499 */
5002Collection.prototype.group = function() { return aggregation.group; }();
501
502/**
503 * Returns the options of the collection.
504 *
505 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the options method or null if an error occured.
506 * @return {null}
507 * @api public
508 */
5092Collection.prototype.options = function() { return commands.options; }();
510
511/**
512 * Returns if the collection is a capped collection
513 *
514 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the isCapped method or null if an error occured.
515 * @return {null}
516 * @api public
517 */
5182Collection.prototype.isCapped = function() { return commands.isCapped; }();
519
520/**
521 * Checks if one or more indexes exist on the collection
522 *
523 * @param {String|Array} indexNames check if one or more indexes exist on the collection.
524 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexExists method or null if an error occured.
525 * @return {null}
526 * @api public
527 */
5282Collection.prototype.indexExists = function() { return index.indexExists; }();
529
530/**
531 * Execute the geoNear command to search for items in the collection
532 *
533 * Options
534 * - **num** {Number}, max number of results to return.
535 * - **maxDistance** {Number}, include results up to maxDistance from the point.
536 * - **distanceMultiplier** {Number}, include a value to multiply the distances with allowing for range conversions.
537 * - **query** {Object}, filter the results by a query.
538 * - **spherical** {Boolean, default:false}, perform query using a spherical model.
539 * - **uniqueDocs** {Boolean, default:false}, the closest location in a document to the center of the search region will always be returned MongoDB > 2.X.
540 * - **includeLocs** {Boolean, default:false}, include the location data fields in the top level of the results MongoDB > 2.X.
541 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
542 *
543 * @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order.
544 * @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order.
545 * @param {Objects} [options] options for the map reduce job.
546 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoNear method or null if an error occured.
547 * @return {null}
548 * @api public
549 */
5502Collection.prototype.geoNear = function() { return geo.geoNear; }();
551
552/**
553 * Execute a geo search using a geo haystack index on a collection.
554 *
555 * Options
556 * - **maxDistance** {Number}, include results up to maxDistance from the point.
557 * - **search** {Object}, filter the results by a query.
558 * - **limit** {Number}, max number of results to return.
559 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
560 *
561 * @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order.
562 * @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order.
563 * @param {Objects} [options] options for the map reduce job.
564 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoHaystackSearch method or null if an error occured.
565 * @return {null}
566 * @api public
567 */
5682Collection.prototype.geoHaystackSearch = function() { return geo.geoHaystackSearch; }();
569
570/**
571 * Retrieve all the indexes on the collection.
572 *
573 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexes method or null if an error occured.
574 * @return {null}
575 * @api public
576 */
5771Collection.prototype.indexes = function indexes(callback) {
5780 this.db.indexInformation(this.collectionName, {full:true}, callback);
579}
580
581/**
582 * Execute an aggregation framework pipeline against the collection, needs MongoDB >= 2.2
583 *
584 * Options
585 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
586 *
587 * @param {Array} array containing all the aggregation framework commands for the execution.
588 * @param {Object} [options] additional options during update.
589 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the aggregate method or null if an error occured.
590 * @return {null}
591 * @api public
592 */
5932Collection.prototype.aggregate = function() { return aggregation.aggregate; }();
594
595/**
596 * Get all the collection statistics.
597 *
598 * Options
599 * - **scale** {Number}, divide the returned sizes by scale value.
600 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
601 *
602 * @param {Objects} [options] options for the stats command.
603 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the stats method or null if an error occured.
604 * @return {null}
605 * @api public
606 */
6072Collection.prototype.stats = function() { return commands.stats; }();
608
609/**
610 * @ignore
611 */
6121Object.defineProperty(Collection.prototype, "hint", {
613 enumerable: true
614 , get: function () {
6150 return this.internalHint;
616 }
617 , set: function (v) {
6180 this.internalHint = shared.normalizeHintField(v);
619 }
620});
621
622/**
623 * Expose.
624 */
6251exports.Collection = Collection;
626

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/collection/aggregation.js

7%
150
11
139
LineHitsSource
11var shared = require('./shared')
2 , utils = require('../utils')
3 , AggregationCursor = require('../aggregation_cursor').AggregationCursor
4 , Code = require('bson').Code
5 , DbCommand = require('../commands/db_command').DbCommand;
6
7/**
8 * Functions that are passed as scope args must
9 * be converted to Code instances.
10 * @ignore
11 */
121function processScope (scope) {
130 if (!utils.isObject(scope)) {
140 return scope;
15 }
16
170 var keys = Object.keys(scope);
180 var i = keys.length;
190 var key;
20
210 while (i--) {
220 key = keys[i];
230 if ('function' == typeof scope[key]) {
240 scope[key] = new Code(String(scope[key]));
25 } else {
260 scope[key] = processScope(scope[key]);
27 }
28 }
29
300 return scope;
31}
32
331var pipe = function() {
340 return new AggregationCursor(this, this.serverCapabilities);
35}
36
371var mapReduce = function mapReduce (map, reduce, options, callback) {
380 if ('function' === typeof options) callback = options, options = {};
39 // Out must allways be defined (make sure we don't break weirdly on pre 1.8+ servers)
400 if(null == options.out) {
410 throw new Error("the out option parameter must be defined, see mongodb docs for possible values");
42 }
43
440 if ('function' === typeof map) {
450 map = map.toString();
46 }
47
480 if ('function' === typeof reduce) {
490 reduce = reduce.toString();
50 }
51
520 if ('function' === typeof options.finalize) {
530 options.finalize = options.finalize.toString();
54 }
55
560 var mapCommandHash = {
57 mapreduce: this.collectionName
58 , map: map
59 , reduce: reduce
60 };
61
62 // Add any other options passed in
630 for (var name in options) {
640 if ('scope' == name) {
650 mapCommandHash[name] = processScope(options[name]);
66 } else {
670 mapCommandHash[name] = options[name];
68 }
69 }
70
71 // Set read preference if we set one
720 var readPreference = shared._getReadConcern(this, options);
73
74 // If we have a read preference and inline is not set as output fail hard
750 if((readPreference != false && readPreference != 'primary')
76 && options['out'] && (options['out'].inline != 1 && options['out'] != 'inline')) {
770 readPreference = 'primary';
78 }
79
80 // self
810 var self = this;
820 var cmd = DbCommand.createDbCommand(this.db, mapCommandHash);
83
840 this.db._executeQueryCommand(cmd, {read:readPreference}, function (err, result) {
850 if(err) return callback(err);
860 if(!result || !result.documents || result.documents.length == 0)
870 return callback(Error("command failed to return results"), null)
88
89 // Check if we have an error
900 if(1 != result.documents[0].ok || result.documents[0].err || result.documents[0].errmsg) {
910 return callback(utils.toError(result.documents[0]));
92 }
93
94 // Create statistics value
950 var stats = {};
960 if(result.documents[0].timeMillis) stats['processtime'] = result.documents[0].timeMillis;
970 if(result.documents[0].counts) stats['counts'] = result.documents[0].counts;
980 if(result.documents[0].timing) stats['timing'] = result.documents[0].timing;
99
100 // invoked with inline?
1010 if(result.documents[0].results) {
102 // If we wish for no verbosity
1030 if(options['verbose'] == null || !options['verbose']) {
1040 return callback(null, result.documents[0].results);
105 }
1060 return callback(null, result.documents[0].results, stats);
107 }
108
109 // The returned collection
1100 var collection = null;
111
112 // If we have an object it's a different db
1130 if(result.documents[0].result != null && typeof result.documents[0].result == 'object') {
1140 var doc = result.documents[0].result;
1150 collection = self.db.db(doc.db).collection(doc.collection);
116 } else {
117 // Create a collection object that wraps the result collection
1180 collection = self.db.collection(result.documents[0].result)
119 }
120
121 // If we wish for no verbosity
1220 if(options['verbose'] == null || !options['verbose']) {
1230 return callback(err, collection);
124 }
125
126 // Return stats as third set of values
1270 callback(err, collection, stats);
128 });
129};
130
131/**
132 * Group function helper
133 * @ignore
134 */
1351var groupFunction = function () {
1360 var c = db[ns].find(condition);
1370 var map = new Map();
1380 var reduce_function = reduce;
139
1400 while (c.hasNext()) {
1410 var obj = c.next();
1420 var key = {};
143
1440 for (var i = 0, len = keys.length; i < len; ++i) {
1450 var k = keys[i];
1460 key[k] = obj[k];
147 }
148
1490 var aggObj = map.get(key);
150
1510 if (aggObj == null) {
1520 var newObj = Object.extend({}, key);
1530 aggObj = Object.extend(newObj, initial);
1540 map.put(key, aggObj);
155 }
156
1570 reduce_function(obj, aggObj);
158 }
159
1600 return { "result": map.values() };
161}.toString();
162
1631var group = function group(keys, condition, initial, reduce, finalize, command, options, callback) {
1640 var args = Array.prototype.slice.call(arguments, 3);
1650 callback = args.pop();
166 // Fetch all commands
1670 reduce = args.length ? args.shift() : null;
1680 finalize = args.length ? args.shift() : null;
1690 command = args.length ? args.shift() : null;
1700 options = args.length ? args.shift() || {} : {};
171
172 // Make sure we are backward compatible
1730 if(!(typeof finalize == 'function')) {
1740 command = finalize;
1750 finalize = null;
176 }
177
1780 if (!Array.isArray(keys) && keys instanceof Object && typeof(keys) !== 'function' && !(keys instanceof Code)) {
1790 keys = Object.keys(keys);
180 }
181
1820 if(typeof reduce === 'function') {
1830 reduce = reduce.toString();
184 }
185
1860 if(typeof finalize === 'function') {
1870 finalize = finalize.toString();
188 }
189
190 // Set up the command as default
1910 command = command == null ? true : command;
192
193 // Execute using the command
1940 if(command) {
1950 var reduceFunction = reduce instanceof Code
196 ? reduce
197 : new Code(reduce);
198
1990 var selector = {
200 group: {
201 'ns': this.collectionName
202 , '$reduce': reduceFunction
203 , 'cond': condition
204 , 'initial': initial
205 , 'out': "inline"
206 }
207 };
208
209 // if finalize is defined
2100 if(finalize != null) selector.group['finalize'] = finalize;
211 // Set up group selector
2120 if ('function' === typeof keys || keys instanceof Code) {
2130 selector.group.$keyf = keys instanceof Code
214 ? keys
215 : new Code(keys);
216 } else {
2170 var hash = {};
2180 keys.forEach(function (key) {
2190 hash[key] = 1;
220 });
2210 selector.group.key = hash;
222 }
223
2240 var cmd = DbCommand.createDbSlaveOkCommand(this.db, selector);
225 // Set read preference if we set one
2260 var readPreference = shared._getReadConcern(this, options);
227 // Execute the command
2280 this.db._executeQueryCommand(cmd
229 , {read:readPreference}
230 , utils.handleSingleCommandResultReturn(null, null, function(err, result) {
2310 if(err) return callback(err, null);
2320 callback(null, result.retval);
233 }));
234 } else {
235 // Create execution scope
2360 var scope = reduce != null && reduce instanceof Code
237 ? reduce.scope
238 : {};
239
2400 scope.ns = this.collectionName;
2410 scope.keys = keys;
2420 scope.condition = condition;
2430 scope.initial = initial;
244
245 // Pass in the function text to execute within mongodb.
2460 var groupfn = groupFunction.replace(/ reduce;/, reduce.toString() + ';');
247
2480 this.db.eval(new Code(groupfn, scope), function (err, results) {
2490 if (err) return callback(err, null);
2500 callback(null, results.result || results);
251 });
252 }
253};
254
2551var aggregate = function(pipeline, options, callback) {
2560 var args = Array.prototype.slice.call(arguments, 0);
2570 callback = args.pop();
2580 var self = this;
259
260 // If we have any of the supported options in the options object
2610 var opts = args[args.length - 1];
2620 options = opts.readPreference
263 || opts.explain
264 || opts.cursor
265 || opts.out
266 || opts.allowDiskUsage ? args.pop() : {}
267 // If the callback is the option (as for cursor override it)
2680 if(typeof callback == 'object' && callback != null) options = callback;
269
270 // Convert operations to an array
2710 if(!Array.isArray(args[0])) {
2720 pipeline = [];
273 // Push all the operations to the pipeline
2740 for(var i = 0; i < args.length; i++) pipeline.push(args[i]);
275 }
276
277 // Is the user requesting a cursor
2780 if(options.cursor != null && options.out == null) {
279 // Set the aggregation cursor options
2800 var agg_cursor_options = options.cursor;
2810 agg_cursor_options.pipe = pipeline;
2820 agg_cursor_options.allowDiskUsage = options.allowDiskUsage == null ? false : options.allowDiskUsage;
283 // Return the aggregation cursor
2840 return new AggregationCursor(this, this.serverCapabilities, agg_cursor_options);
285 }
286
287 // If out was specified
2880 if(typeof options.out == 'string') {
2890 pipeline.push({$out: options.out});
290 }
291
292 // Build the command
2930 var command = { aggregate : this.collectionName, pipeline : pipeline};
294 // If we have allowDiskUsage defined
2950 if(options.allowDiskUsage) command.allowDiskUsage = options.allowDiskUsage;
296
297 // Ensure we have the right read preference inheritance
2980 options.readPreference = shared._getReadConcern(this, options);
299 // If explain has been specified add it
3000 if(options.explain) command.explain = options.explain;
301 // Execute the command
3020 this.db.command(command, options, function(err, result) {
3030 if(err) {
3040 callback(err);
3050 } else if(result['err'] || result['errmsg']) {
3060 callback(utils.toError(result));
3070 } else if(typeof result == 'object' && result['serverPipeline']) {
3080 callback(null, result['serverPipeline']);
3090 } else if(typeof result == 'object' && result['stages']) {
3100 callback(null, result['stages']);
311 } else {
3120 callback(null, result.result);
313 }
314 });
315}
316
3171exports.mapReduce = mapReduce;
3181exports.group = group;
3191exports.aggregate = aggregate;
3201exports.pipe = pipe;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/collection/commands.js

18%
71
13
58
LineHitsSource
11var shared = require('./shared')
2 , utils = require('../utils')
3 , DbCommand = require('../commands/db_command').DbCommand;
4
51var stats = function stats(options, callback) {
60 var args = Array.prototype.slice.call(arguments, 0);
70 callback = args.pop();
8 // Fetch all commands
90 options = args.length ? args.shift() || {} : {};
10
11 // Build command object
120 var commandObject = {
13 collStats:this.collectionName,
14 }
15
16 // Check if we have the scale value
170 if(options['scale'] != null) commandObject['scale'] = options['scale'];
18
19 // Ensure we have the right read preference inheritance
200 options.readPreference = shared._getReadConcern(this, options);
21
22 // Execute the command
230 this.db.command(commandObject, options, callback);
24}
25
261var count = function count(query, options, callback) {
270 var args = Array.prototype.slice.call(arguments, 0);
280 callback = args.pop();
290 query = args.length ? args.shift() || {} : {};
300 options = args.length ? args.shift() || {} : {};
310 var skip = options.skip;
320 var limit = options.limit;
330 var maxTimeMS = options.maxTimeMS;
34
35 // Final query
360 var commandObject = {
37 'count': this.collectionName
38 , 'query': query
39 , 'fields': null
40 };
41
42 // Add limit and skip if defined
430 if(typeof skip == 'number') commandObject.skip = skip;
440 if(typeof limit == 'number') commandObject.limit = limit;
450 if(typeof maxTimeMS == 'number') commandObject['$maxTimeMS'] = maxTimeMS;
46
47 // Set read preference if we set one
480 var readPreference = shared._getReadConcern(this, options);
49 // Execute the command
500 this.db._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this.db, commandObject)
51 , {read: readPreference}
52 , utils.handleSingleCommandResultReturn(null, null, function(err, result) {
530 if(err) return callback(err, null);
540 if(result == null) return callback(new Error("no result returned for count"), null);
550 callback(null, result.n);
56 }));
57};
58
591var distinct = function distinct(key, query, options, callback) {
600 var args = Array.prototype.slice.call(arguments, 1);
610 callback = args.pop();
620 query = args.length ? args.shift() || {} : {};
630 options = args.length ? args.shift() || {} : {};
64
650 var mapCommandHash = {
66 'distinct': this.collectionName
67 , 'query': query
68 , 'key': key
69 };
70
71 // Set read preference if we set one
720 var readPreference = options['readPreference'] ? options['readPreference'] : false;
73 // Create the command
740 var cmd = DbCommand.createDbSlaveOkCommand(this.db, mapCommandHash);
75
760 this.db._executeQueryCommand(cmd, {read:readPreference}, function (err, result) {
770 if(err)
780 return callback(err);
790 if(result.documents[0].ok != 1)
800 return callback(new Error(result.documents[0].errmsg));
810 callback(null, result.documents[0].values);
82 });
83};
84
851var rename = function rename (newName, options, callback) {
860 var self = this;
870 if(typeof options == 'function') {
880 callback = options;
890 options = {}
90 }
91
92 // Get collection class
930 var Collection = require('../collection').Collection;
94 // Ensure the new name is valid
950 shared.checkCollectionName(newName);
96
97 // Execute the command, return the new renamed collection if successful
980 self.db._executeQueryCommand(DbCommand.createRenameCollectionCommand(self.db, self.collectionName, newName, options)
99 , utils.handleSingleCommandResultReturn(true, false, function(err, result) {
1000 if(err) return callback(err, null)
1010 try {
1020 if(options.new_collection)
1030 return callback(null, new Collection(self.db, newName, self.db.pkFactory));
1040 self.collectionName = newName;
1050 callback(null, self);
106 } catch(err) {
1070 callback(err, null);
108 }
109 }));
110};
111
1121var options = function options(callback) {
1130 this.db.collectionsInfo(this.collectionName, function (err, cursor) {
1140 if (err) return callback(err);
1150 cursor.nextObject(function (err, document) {
1160 callback(err, document && document.options || null);
117 });
118 });
119};
120
1211var isCapped = function isCapped(callback) {
1220 this.options(function(err, document) {
1230 if(err != null) {
1240 callback(err);
125 } else {
1260 callback(null, document && document.capped);
127 }
128 });
129};
130
1311exports.stats = stats;
1321exports.count = count;
1331exports.distinct = distinct;
1341exports.rename = rename;
1351exports.options = options;
1361exports.isCapped = isCapped;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/collection/core.js

6%
315
19
296
LineHitsSource
11var InsertCommand = require('../commands/insert_command').InsertCommand
2 , DeleteCommand = require('../commands/delete_command').DeleteCommand
3 , UpdateCommand = require('../commands/update_command').UpdateCommand
4 , DbCommand = require('../commands/db_command').DbCommand
5 , utils = require('../utils')
6 , hasWriteCommands = require('../utils').hasWriteCommands
7 , shared = require('./shared');
8
9/**
10 * Precompiled regexes
11 * @ignore
12 **/
131var eErrorMessages = /No matching object found/;
14
15// ***************************************************
16// Insert function
17// ***************************************************
181var insert = function insert (docs, options, callback) {
190 if ('function' === typeof options) callback = options, options = {};
200 if(options == null) options = {};
210 if(!('function' === typeof callback)) callback = null;
22
23 // Get a connection
240 var connection = this.db.serverConfig.checkoutWriter();
250 var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true;
26 // If we support write commands let's perform the insert using it
270 if(!useLegacyOps && hasWriteCommands(connection)
28 && !Buffer.isBuffer(docs)
29 && (!Array.isArray(docs) && docs.length > 0 && !Buffer.isBuffer(docs[0]))) {
300 insertWithWriteCommands(this, Array.isArray(docs) ? docs : [docs], options, callback);
310 return this
32 }
33
34 // Backwards compatibility
350 insertAll(this, Array.isArray(docs) ? docs : [docs], options, callback);
360 return this;
37};
38
39//
40// Uses the new write commands available from 2.6 >
41//
421var insertWithWriteCommands = function(self, docs, options, callback) {
43 // Get the intended namespace for the operation
440 var namespace = self.collectionName;
45
46 // Ensure we have no \x00 bytes in the name causing wrong parsing
470 if(!!~namespace.indexOf("\x00")) {
480 return callback(new Error("namespace cannot contain a null character"), null);
49 }
50
51 // Check if we have passed in continue on error
520 var continueOnError = typeof options['keepGoing'] == 'boolean'
53 ? options['keepGoing'] : false;
540 continueOnError = typeof options['continueOnError'] == 'boolean'
55 ? options['continueOnError'] : continueOnError;
56
57 // Do we serialzie functions
580 var serializeFunctions = typeof options.serializeFunctions != 'boolean'
59 ? self.serializeFunctions : options.serializeFunctions;
60
61 // Checkout a write connection
620 var connection = self.db.serverConfig.checkoutWriter();
63
64 // Collect errorOptions
650 var errorOptions = shared._getWriteConcern(self, options);
66
67 // If we have a write command with no callback and w:0 fail
680 if(errorOptions.w && errorOptions.w != 0 && callback == null) {
690 throw new Error("writeConcern requires callback")
70 }
71
72 // Add the documents and decorate them with id's if they have none
730 for(var index = 0, len = docs.length; index < len; ++index) {
740 var doc = docs[index];
75
76 // Add id to each document if it's not already defined
770 if (!(Buffer.isBuffer(doc))
78 && doc['_id'] == null
79 && self.db.forceServerObjectId != true
80 && options.forceServerObjectId != true) {
810 doc['_id'] = self.pkFactory.createPk();
82 }
83 }
84
85 // Create the write command
860 var write_command = {
87 insert: namespace
88 , writeConcern: errorOptions
89 , ordered: !continueOnError
90 , documents: docs
91 }
92
93 // Execute the write command
940 self.db.command(write_command
95 , { connection:connection
96 , checkKeys: true
97 , serializeFunctions: serializeFunctions
98 , writeCommand: true }
99 , function(err, result) {
1000 if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null);
1010 if(errorOptions.w == 0) return;
1020 if(callback == null) return;
1030 if(err != null) {
104 // Rewrite for backward compatibility
1050 if(Array.isArray(err.errDetails)) err.code = err.errDetails[0].errCode;
106 // Return the error
1070 return callback(err, null);
108 }
109
110 // Result has an error
1110 if(!result.ok && (result.err != null || result.errmsg != null)) {
112 // Map the error
1130 var error = utils.toError(result);
114 // Backwards compatibility mapping
1150 if(Array.isArray(error.errDetails)) error.code = error.errDetails[0].errCode;
116 // Return the error
1170 return callback(error, null);
118 }
119
120 // Return the results for a whole batch
1210 callback(null, docs)
122 });
123}
124
125//
126// Uses pre 2.6 OP_INSERT wire protocol
127//
1281var insertAll = function insertAll (self, docs, options, callback) {
1290 if('function' === typeof options) callback = options, options = {};
1300 if(options == null) options = {};
1310 if(!('function' === typeof callback)) callback = null;
132
133 // Insert options (flags for insert)
1340 var insertFlags = {};
135 // If we have a mongodb version >= 1.9.1 support keepGoing attribute
1360 if(options['keepGoing'] != null) {
1370 insertFlags['keepGoing'] = options['keepGoing'];
138 }
139
140 // If we have a mongodb version >= 1.9.1 support keepGoing attribute
1410 if(options['continueOnError'] != null) {
1420 insertFlags['continueOnError'] = options['continueOnError'];
143 }
144
145 // DbName
1460 var dbName = options['dbName'];
147 // If no dbname defined use the db one
1480 if(dbName == null) {
1490 dbName = self.db.databaseName;
150 }
151
152 // Either use override on the function, or go back to default on either the collection
153 // level or db
1540 if(options['serializeFunctions'] != null) {
1550 insertFlags['serializeFunctions'] = options['serializeFunctions'];
156 } else {
1570 insertFlags['serializeFunctions'] = self.serializeFunctions;
158 }
159
160 // Get checkKeys value
1610 var checkKeys = typeof options.checkKeys != 'boolean' ? true : options.checkKeys;
162
163 // Pass in options
1640 var insertCommand = new InsertCommand(
165 self.db
166 , dbName + "." + self.collectionName, checkKeys, insertFlags);
167
168 // Add the documents and decorate them with id's if they have none
1690 for(var index = 0, len = docs.length; index < len; ++index) {
1700 var doc = docs[index];
171
172 // Add id to each document if it's not already defined
1730 if (!(Buffer.isBuffer(doc))
174 && doc['_id'] == null
175 && self.db.forceServerObjectId != true
176 && options.forceServerObjectId != true) {
1770 doc['_id'] = self.pkFactory.createPk();
178 }
179
1800 insertCommand.add(doc);
181 }
182
183 // Collect errorOptions
1840 var errorOptions = shared._getWriteConcern(self, options);
185 // Default command options
1860 var commandOptions = {};
187 // If safe is defined check for error message
1880 if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') {
189 // Insert options
1900 commandOptions['read'] = false;
191 // If we have safe set set async to false
1920 if(errorOptions == null) commandOptions['async'] = true;
193
194 // Set safe option
1950 commandOptions['safe'] = errorOptions;
196 // If we have an error option
1970 if(typeof errorOptions == 'object') {
1980 var keys = Object.keys(errorOptions);
1990 for(var i = 0; i < keys.length; i++) {
2000 commandOptions[keys[i]] = errorOptions[keys[i]];
201 }
202 }
203
204 // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection)
2050 self.db._executeInsertCommand(insertCommand, commandOptions, function (err, error) {
2060 error = error && error.documents;
2070 if(!callback) return;
208
2090 if (err) {
2100 callback(err);
2110 } else if(error[0].err || error[0].errmsg) {
2120 callback(utils.toError(error[0]));
2130 } else if(error[0].jnote || error[0].wnote || error[0].wtimeout) {
2140 callback(utils.toError(error[0]));
215 } else {
2160 callback(null, docs);
217 }
218 });
2190 } else if(shared._hasWriteConcern(errorOptions) && callback == null) {
2200 throw new Error("Cannot use a writeConcern without a provided callback");
221 } else {
222 // Execute the call without a write concern
2230 var result = self.db._executeInsertCommand(insertCommand, commandOptions);
224 // If no callback just return
2250 if(!callback) return;
226 // If error return error
2270 if(result instanceof Error) {
2280 return callback(result);
229 }
230
231 // Otherwise just return
2320 return callback(null, docs);
233 }
234};
235
236// ***************************************************
237// Remove function
238// ***************************************************
2391var removeWithWriteCommands = function(self, selector, options, callback) {
2400 if ('function' === typeof selector) {
2410 callback = selector;
2420 selector = options = {};
2430 } else if ('function' === typeof options) {
2440 callback = options;
2450 options = {};
246 }
247
248 // Get the intended namespace for the operation
2490 var namespace = self.collectionName;
250
251 // Ensure we have no \x00 bytes in the name causing wrong parsing
2520 if(!!~namespace.indexOf("\x00")) {
2530 return callback(new Error("namespace cannot contain a null character"), null);
254 }
255
256 // Set default empty selector if none
2570 selector = selector == null ? {} : selector;
258
259 // Check if we have passed in continue on error
2600 var continueOnError = typeof options['keepGoing'] == 'boolean'
261 ? options['keepGoing'] : false;
2620 continueOnError = typeof options['continueOnError'] == 'boolean'
263 ? options['continueOnError'] : continueOnError;
264
265 // Do we serialzie functions
2660 var serializeFunctions = typeof options.serializeFunctions != 'boolean'
267 ? self.serializeFunctions : options.serializeFunctions;
268
269 // Checkout a write connection
2700 var connection = self.db.serverConfig.checkoutWriter();
271
272 // Figure out the value of top
2730 var limit = options.single == true ? 1 : 0;
2740 var upsert = typeof options.upsert == 'boolean' ? options.upsert : false;
275
276 // Collect errorOptions
2770 var errorOptions = shared._getWriteConcern(self, options);
278
279 // If we have a write command with no callback and w:0 fail
2800 if(errorOptions.w && errorOptions.w != 0 && callback == null) {
2810 throw new Error("writeConcern requires callback")
282 }
283
284 // Create the write command
2850 var write_command = {
286 delete: namespace,
287 writeConcern: errorOptions,
288 ordered: !continueOnError,
289 deletes: [{
290 q : selector,
291 limit: limit
292 }]
293 }
294
295 // Execute the write command
2960 self.db.command(write_command
297 , { connection:connection
298 , checkKeys: true
299 , serializeFunctions: serializeFunctions
300 , writeCommand: true }
301 , function(err, result) {
3020 if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null);
3030 if(errorOptions.w == 0) return;
3040 if(callback == null) return;
3050 if(err != null) {
3060 if(Array.isArray(err.errDetails)) err.code = err.errDetails[0].errCode;
307 // Return the error
3080 return callback(err, null);
309 }
310
311 // Result has an error
3120 if(!result.ok && (result.err != null || result.errmsg != null)) {
313 // Map the error
3140 var error = utils.toError(result);
315 // Backwards compatibility mapping
3160 if(Array.isArray(error.errDetails)) error.code = error.errDetails[0].errCode;
317 // Return the error
3180 return callback(error, null);
319 }
320
321 // Backward compatibility format
3220 var r = backWardsCompatibiltyResults(result, 'remove');
323 // Return the results for a whole batch
3240 callback(null, r.n, r)
325 });
326}
327
3281var remove = function remove(selector, options, callback) {
3290 if('function' === typeof options) callback = options, options = null;
3300 if(options == null) options = {};
3310 if(!('function' === typeof callback)) callback = null;
332 // Get a connection
3330 var connection = this.db.serverConfig.checkoutWriter();
3340 var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true;
335 // If we support write commands let's perform the insert using it
3360 if(!useLegacyOps && hasWriteCommands(connection) && !Buffer.isBuffer(selector)) {
3370 return removeWithWriteCommands(this, selector, options, callback);
338 }
339
3400 if ('function' === typeof selector) {
3410 callback = selector;
3420 selector = options = {};
3430 } else if ('function' === typeof options) {
3440 callback = options;
3450 options = {};
346 }
347
348 // Ensure options
3490 if(options == null) options = {};
3500 if(!('function' === typeof callback)) callback = null;
351 // Ensure we have at least an empty selector
3520 selector = selector == null ? {} : selector;
353 // Set up flags for the command, if we have a single document remove
3540 var flags = 0 | (options.single ? 1 : 0);
355
356 // DbName
3570 var dbName = options['dbName'];
358 // If no dbname defined use the db one
3590 if(dbName == null) {
3600 dbName = this.db.databaseName;
361 }
362
363 // Create a delete command
3640 var deleteCommand = new DeleteCommand(
365 this.db
366 , dbName + "." + this.collectionName
367 , selector
368 , flags);
369
3700 var self = this;
3710 var errorOptions = shared._getWriteConcern(self, options);
372 // Execute the command, do not add a callback as it's async
3730 if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') {
374 // Insert options
3750 var commandOptions = {read:false};
376 // If we have safe set set async to false
3770 if(errorOptions == null) commandOptions['async'] = true;
378 // Set safe option
3790 commandOptions['safe'] = true;
380 // If we have an error option
3810 if(typeof errorOptions == 'object') {
3820 var keys = Object.keys(errorOptions);
3830 for(var i = 0; i < keys.length; i++) {
3840 commandOptions[keys[i]] = errorOptions[keys[i]];
385 }
386 }
387
388 // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection)
3890 this.db._executeRemoveCommand(deleteCommand, commandOptions, function (err, error) {
3900 error = error && error.documents;
3910 if(!callback) return;
392
3930 if(err) {
3940 callback(err);
3950 } else if(error[0].err || error[0].errmsg) {
3960 callback(utils.toError(error[0]));
3970 } else if(error[0].jnote || error[0].wnote || error[0].wtimeout) {
3980 callback(utils.toError(error[0]));
399 } else {
4000 callback(null, error[0].n);
401 }
402 });
4030 } else if(shared._hasWriteConcern(errorOptions) && callback == null) {
4040 throw new Error("Cannot use a writeConcern without a provided callback");
405 } else {
4060 var result = this.db._executeRemoveCommand(deleteCommand);
407 // If no callback just return
4080 if (!callback) return;
409 // If error return error
4100 if (result instanceof Error) {
4110 return callback(result);
412 }
413 // Otherwise just return
4140 return callback();
415 }
416};
417
418// ***************************************************
419// Save function
420// ***************************************************
4211var save = function save(doc, options, callback) {
4220 if('function' === typeof options) callback = options, options = null;
4230 if(options == null) options = {};
4240 if(!('function' === typeof callback)) callback = null;
425 // Throw an error if attempting to perform a bulk operation
4260 if(Array.isArray(doc)) throw new Error("doc parameter must be a single document");
427 // Extract the id, if we have one we need to do a update command
4280 var id = doc['_id'];
4290 var commandOptions = shared._getWriteConcern(this, options);
430
4310 if(id != null) {
4320 commandOptions.upsert = true;
4330 this.update({ _id: id }, doc, commandOptions, callback);
434 } else {
4350 this.insert(doc, commandOptions, callback && function (err, docs) {
4360 if(err) return callback(err, null);
437
4380 if(Array.isArray(docs)) {
4390 callback(err, docs[0]);
440 } else {
4410 callback(err, docs);
442 }
443 });
444 }
445};
446
447// ***************************************************
448// Update document function
449// ***************************************************
4501var updateWithWriteCommands = function(self, selector, document, options, callback) {
4510 if('function' === typeof options) callback = options, options = null;
4520 if(options == null) options = {};
4530 if(!('function' === typeof callback)) callback = null;
454
455 // Get the intended namespace for the operation
4560 var namespace = self.collectionName;
457
458 // Ensure we have no \x00 bytes in the name causing wrong parsing
4590 if(!!~namespace.indexOf("\x00")) {
4600 return callback(new Error("namespace cannot contain a null character"), null);
461 }
462
463 // If we are not providing a selector or document throw
4640 if(selector == null || typeof selector != 'object')
4650 return callback(new Error("selector must be a valid JavaScript object"));
4660 if(document == null || typeof document != 'object')
4670 return callback(new Error("document must be a valid JavaScript object"));
468
469 // Check if we have passed in continue on error
4700 var continueOnError = typeof options['keepGoing'] == 'boolean'
471 ? options['keepGoing'] : false;
4720 continueOnError = typeof options['continueOnError'] == 'boolean'
473 ? options['continueOnError'] : continueOnError;
474
475 // Do we serialzie functions
4760 var serializeFunctions = typeof options.serializeFunctions != 'boolean'
477 ? self.serializeFunctions : options.serializeFunctions;
478
479 // Checkout a write connection
4800 var connection = self.db.serverConfig.checkoutWriter();
481
482 // Figure out the value of top
4830 var multi = typeof options.multi == 'boolean' ? options.multi : false;
4840 var upsert = typeof options.upsert == 'boolean' ? options.upsert : false;
485
486 // Collect errorOptions
4870 var errorOptions = shared._getWriteConcern(self, options);
488
489 // If we have a write command with no callback and w:0 fail
4900 if(errorOptions.w && errorOptions.w != 0 && callback == null) {
4910 throw new Error("writeConcern requires callback")
492 }
493
494 // Create the write command
4950 var write_command = {
496 update: namespace,
497 writeConcern: errorOptions,
498 ordered: !continueOnError,
499 updates: [{
500 q : selector,
501 u: document,
502 multi: multi,
503 upsert: upsert
504 }]
505 }
506
507 // Check if we have a checkKeys override
5080 var checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : false;
509
510 // Execute the write command
5110 self.db.command(write_command
512 , { connection:connection
513 , checkKeys: checkKeys
514 , serializeFunctions: serializeFunctions
515 , writeCommand: true }
516 , function(err, result) {
5170 if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null);
5180 if(errorOptions.w == 0) return;
5190 if(callback == null) return;
5200 if(err != null) {
5210 if(Array.isArray(err.errDetails)) err.code = err.errDetails[0].errCode;
522 // Return the error
5230 return callback(err, null);
524 }
525
526 // Result has an error
5270 if(!result.ok && (result.err != null || result.errmsg != null)) {
528 // Map the error
5290 var error = utils.toError(result);
530 // Backwards compatibility mapping
5310 if(Array.isArray(error.errDetails)) error.code = error.errDetails[0].errCode;
532 // Return the error
5330 return callback(error, null);
534 }
535
536 // Backward compatibility format
5370 var r = backWardsCompatibiltyResults(result, 'update');
538 // Return the results for a whole batch
5390 callback(null, r.n, r)
540 });
541}
542
5431var backWardsCompatibiltyResults = function(result, op) {
544 // Upserted
5450 var upsertedValue = null;
5460 var finalResult = null;
5470 var updatedExisting = true;
548
549 // We have a single document upserted result
5500 if(Array.isArray(result.upserted) || result.upserted != null) {
5510 updatedExisting = false;
5520 upsertedValue = result.upserted;
553 }
554
555 // Final result
5560 if(op == 'remove' || op == 'insert') {
5570 finalResult = {ok: true, n: result.n}
558 } else {
5590 finalResult = {ok: true, n: result.n, updatedExisting: updatedExisting}
560 }
561
5620 if(upsertedValue != null) finalResult.upserted = upsertedValue;
5630 return finalResult;
564}
565
5661var update = function update(selector, document, options, callback) {
5670 if('function' === typeof options) callback = options, options = null;
5680 if(options == null) options = {};
5690 if(!('function' === typeof callback)) callback = null;
570
571 // Get a connection
5720 var connection = this.db.serverConfig.checkoutWriter();
5730 var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true;
574 // If we support write commands let's perform the insert using it
5750 if(!useLegacyOps && hasWriteCommands(connection) && !Buffer.isBuffer(selector) && !Buffer.isBuffer(document)) {
5760 return updateWithWriteCommands(this, selector, document, options, callback);
577 }
578
579 // DbName
5800 var dbName = options['dbName'];
581 // If no dbname defined use the db one
5820 if(dbName == null) {
5830 dbName = this.db.databaseName;
584 }
585
586 // If we are not providing a selector or document throw
5870 if(selector == null || typeof selector != 'object') return callback(new Error("selector must be a valid JavaScript object"));
5880 if(document == null || typeof document != 'object') return callback(new Error("document must be a valid JavaScript object"));
589
590 // Either use override on the function, or go back to default on either the collection
591 // level or db
5920 if(options['serializeFunctions'] != null) {
5930 options['serializeFunctions'] = options['serializeFunctions'];
594 } else {
5950 options['serializeFunctions'] = this.serializeFunctions;
596 }
597
598 // Build the options command
5990 var updateCommand = new UpdateCommand(
600 this.db
601 , dbName + "." + this.collectionName
602 , selector
603 , document
604 , options);
605
6060 var self = this;
607 // Unpack the error options if any
6080 var errorOptions = shared._getWriteConcern(this, options);
609 // If safe is defined check for error message
6100 if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') {
611 // Insert options
6120 var commandOptions = {read:false};
613 // If we have safe set set async to false
6140 if(errorOptions == null) commandOptions['async'] = true;
615 // Set safe option
6160 commandOptions['safe'] = errorOptions;
617 // If we have an error option
6180 if(typeof errorOptions == 'object') {
6190 var keys = Object.keys(errorOptions);
6200 for(var i = 0; i < keys.length; i++) {
6210 commandOptions[keys[i]] = errorOptions[keys[i]];
622 }
623 }
624
625 // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection)
6260 this.db._executeUpdateCommand(updateCommand, commandOptions, function (err, error) {
6270 error = error && error.documents;
6280 if(!callback) return;
629
6300 if(err) {
6310 callback(err);
6320 } else if(error[0].err || error[0].errmsg) {
6330 callback(utils.toError(error[0]));
6340 } else if(error[0].jnote || error[0].wnote || error[0].wtimeout) {
6350 callback(utils.toError(error[0]));
636 } else {
6370 callback(null, error[0].n, error[0]);
638 }
639 });
6400 } else if(shared._hasWriteConcern(errorOptions) && callback == null) {
6410 throw new Error("Cannot use a writeConcern without a provided callback");
642 } else {
643 // Execute update
6440 var result = this.db._executeUpdateCommand(updateCommand);
645 // If no callback just return
6460 if (!callback) return;
647 // If error return error
6480 if (result instanceof Error) {
6490 return callback(result);
650 }
651 // Otherwise just return
6520 return callback();
653 }
654};
655
656// ***************************************************
657// findAndModify function
658// ***************************************************
6591var findAndModify = function findAndModify (query, sort, doc, options, callback) {
6600 var args = Array.prototype.slice.call(arguments, 1);
6610 callback = args.pop();
6620 sort = args.length ? args.shift() || [] : [];
6630 doc = args.length ? args.shift() : null;
6640 options = args.length ? args.shift() || {} : {};
6650 var self = this;
666
6670 var queryObject = {
668 'findandmodify': this.collectionName
669 , 'query': query
670 , 'sort': utils.formattedOrderClause(sort)
671 };
672
6730 queryObject.new = options.new ? 1 : 0;
6740 queryObject.remove = options.remove ? 1 : 0;
6750 queryObject.upsert = options.upsert ? 1 : 0;
676
6770 if (options.fields) {
6780 queryObject.fields = options.fields;
679 }
680
6810 if (doc && !options.remove) {
6820 queryObject.update = doc;
683 }
684
685 // Checkout a write connection
6860 options.connection = self.db.serverConfig.checkoutWriter();
687
688 // Either use override on the function, or go back to default on either the collection
689 // level or db
6900 if(options['serializeFunctions'] != null) {
6910 options['serializeFunctions'] = options['serializeFunctions'];
692 } else {
6930 options['serializeFunctions'] = this.serializeFunctions;
694 }
695
696 // No check on the documents
6970 options.checkKeys = false
698
699 // Execute the command
7000 this.db.command(queryObject
701 , options, function(err, result) {
7020 if(err) return callback(err, null);
7030 return callback(null, result.value, result);
704 });
705}
706
707// ***************************************************
708// findAndRemove function
709// ***************************************************
7101var findAndRemove = function(query, sort, options, callback) {
7110 var args = Array.prototype.slice.call(arguments, 1);
7120 callback = args.pop();
7130 sort = args.length ? args.shift() || [] : [];
7140 options = args.length ? args.shift() || {} : {};
715 // Add the remove option
7160 options['remove'] = true;
717 // Execute the callback
7180 this.findAndModify(query, sort, null, options, callback);
719}
720
721// Map methods
7221exports.insert = insert;
7231exports.remove = remove;
7241exports.save = save;
7251exports.update = update;
7261exports.findAndModify = findAndModify;
7271exports.findAndRemove = findAndRemove;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/collection/geo.js

13%
38
5
33
LineHitsSource
11var shared = require('./shared')
2 , utils = require('../utils');
3
41var geoNear = function geoNear(x, y, options, callback) {
50 var args = Array.prototype.slice.call(arguments, 2);
60 callback = args.pop();
7 // Fetch all commands
80 options = args.length ? args.shift() || {} : {};
9
10 // Build command object
110 var commandObject = {
12 geoNear:this.collectionName,
13 near: [x, y]
14 }
15
16 // Decorate object if any with known properties
170 if(options['num'] != null) commandObject['num'] = options['num'];
180 if(options['maxDistance'] != null) commandObject['maxDistance'] = options['maxDistance'];
190 if(options['distanceMultiplier'] != null) commandObject['distanceMultiplier'] = options['distanceMultiplier'];
200 if(options['query'] != null) commandObject['query'] = options['query'];
210 if(options['spherical'] != null) commandObject['spherical'] = options['spherical'];
220 if(options['uniqueDocs'] != null) commandObject['uniqueDocs'] = options['uniqueDocs'];
230 if(options['includeLocs'] != null) commandObject['includeLocs'] = options['includeLocs'];
24
25 // Ensure we have the right read preference inheritance
260 options.readPreference = shared._getReadConcern(this, options);
27
28 // Execute the command
290 this.db.command(commandObject, options, function (err, res) {
300 if (err) {
310 callback(err);
320 } else if (res.err || res.errmsg) {
330 callback(utils.toError(res));
34 } else {
35 // should we only be returning res.results here? Not sure if the user
36 // should see the other return information
370 callback(null, res);
38 }
39 });
40}
41
421var geoHaystackSearch = function geoHaystackSearch(x, y, options, callback) {
430 var args = Array.prototype.slice.call(arguments, 2);
440 callback = args.pop();
45 // Fetch all commands
460 options = args.length ? args.shift() || {} : {};
47
48 // Build command object
490 var commandObject = {
50 geoSearch:this.collectionName,
51 near: [x, y]
52 }
53
54 // Decorate object if any with known properties
550 if(options['maxDistance'] != null) commandObject['maxDistance'] = options['maxDistance'];
560 if(options['query'] != null) commandObject['search'] = options['query'];
570 if(options['search'] != null) commandObject['search'] = options['search'];
580 if(options['limit'] != null) commandObject['limit'] = options['limit'];
59
60 // Ensure we have the right read preference inheritance
610 options.readPreference = shared._getReadConcern(this, options);
62
63 // Execute the command
640 this.db.command(commandObject, options, function (err, res) {
650 if (err) {
660 callback(err);
670 } else if (res.err || res.errmsg) {
680 callback(utils.toError(res));
69 } else {
70 // should we only be returning res.results here? Not sure if the user
71 // should see the other return information
720 callback(null, res);
73 }
74 });
75}
76
771exports.geoNear = geoNear;
781exports.geoHaystackSearch = geoHaystackSearch;
79

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/collection/index.js

28%
39
11
28
LineHitsSource
11var _getWriteConcern = require('./shared')._getWriteConcern;
2
31var createIndex = function createIndex (fieldOrSpec, options, callback) {
4 // Clean up call
50 var args = Array.prototype.slice.call(arguments, 1);
60 callback = args.pop();
70 options = args.length ? args.shift() || {} : {};
80 options = typeof callback === 'function' ? options : callback;
90 options = options == null ? {} : options;
10
11 // Collect errorOptions
120 var errorOptions = _getWriteConcern(this, options);
13 // Execute create index
140 this.db.createIndex(this.collectionName, fieldOrSpec, options, callback);
15};
16
171var indexExists = function indexExists(indexes, callback) {
180 this.indexInformation(function(err, indexInformation) {
19 // If we have an error return
200 if(err != null) return callback(err, null);
21 // Let's check for the index names
220 if(Array.isArray(indexes)) {
230 for(var i = 0; i < indexes.length; i++) {
240 if(indexInformation[indexes[i]] == null) {
250 return callback(null, false);
26 }
27 }
28
29 // All keys found return true
300 return callback(null, true);
31 } else {
320 return callback(null, indexInformation[indexes] != null);
33 }
34 });
35}
36
371var dropAllIndexes = function dropIndexes (callback) {
380 this.db.dropIndex(this.collectionName, '*', function (err, result) {
390 if(err) return callback(err, false);
400 callback(null, true);
41 });
42};
43
441var indexInformation = function indexInformation (options, callback) {
45 // Unpack calls
460 var args = Array.prototype.slice.call(arguments, 0);
470 callback = args.pop();
480 options = args.length ? args.shift() || {} : {};
49 // Call the index information
500 this.db.indexInformation(this.collectionName, options, callback);
51};
52
531var ensureIndex = function ensureIndex (fieldOrSpec, options, callback) {
54 // Clean up call
550 if (typeof callback === 'undefined' && typeof options === 'function') {
560 callback = options;
570 options = {};
58 }
59
600 if (options == null) {
610 options = {};
62 }
63
64 // Execute create index
650 this.db.ensureIndex(this.collectionName, fieldOrSpec, options, callback);
66};
67
681exports.createIndex = createIndex;
691exports.indexExists = indexExists;
701exports.dropAllIndexes = dropAllIndexes;
711exports.indexInformation = indexInformation;
721exports.ensureIndex = ensureIndex;
73

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/collection/query.js

8%
75
6
69
LineHitsSource
11var ObjectID = require('bson').ObjectID
2 , Scope = require('../scope').Scope
3 , shared = require('./shared')
4 , utils = require('../utils');
5
61var testForFields = {
7 limit: 1, sort: 1, fields:1, skip: 1, hint: 1, explain: 1, snapshot: 1, timeout: 1, tailable: 1, tailableRetryInterval: 1
8 , numberOfRetries: 1, awaitdata: 1, exhaust: 1, batchSize: 1, returnKey: 1, maxScan: 1, min: 1, max: 1, showDiskLoc: 1
9 , comment: 1, raw: 1, readPreference: 1, partial: 1, read: 1, dbName: 1, oplogReplay: 1
10};
11
12//
13// Find method
14//
151var find = function find () {
160 var options
17 , args = Array.prototype.slice.call(arguments, 0)
18 , has_callback = typeof args[args.length - 1] === 'function'
19 , has_weird_callback = typeof args[0] === 'function'
20 , callback = has_callback ? args.pop() : (has_weird_callback ? args.shift() : null)
21 , len = args.length
22 , selector = len >= 1 ? args[0] : {}
23 , fields = len >= 2 ? args[1] : undefined;
24
250 if(len === 1 && has_weird_callback) {
26 // backwards compat for callback?, options case
270 selector = {};
280 options = args[0];
29 }
30
310 if(len === 2 && !Array.isArray(fields)) {
320 var fieldKeys = Object.getOwnPropertyNames(fields);
330 var is_option = false;
34
350 for(var i = 0; i < fieldKeys.length; i++) {
360 if(testForFields[fieldKeys[i]] != null) {
370 is_option = true;
380 break;
39 }
40 }
41
420 if(is_option) {
430 options = fields;
440 fields = undefined;
45 } else {
460 options = {};
47 }
480 } else if(len === 2 && Array.isArray(fields) && !Array.isArray(fields[0])) {
490 var newFields = {};
50 // Rewrite the array
510 for(var i = 0; i < fields.length; i++) {
520 newFields[fields[i]] = 1;
53 }
54 // Set the fields
550 fields = newFields;
56 }
57
580 if(3 === len) {
590 options = args[2];
60 }
61
62 // Ensure selector is not null
630 selector = selector == null ? {} : selector;
64 // Validate correctness off the selector
650 var object = selector;
660 if(Buffer.isBuffer(object)) {
670 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
680 if(object_size != object.length) {
690 var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
700 error.name = 'MongoError';
710 throw error;
72 }
73 }
74
75 // Validate correctness of the field selector
760 var object = fields;
770 if(Buffer.isBuffer(object)) {
780 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
790 if(object_size != object.length) {
800 var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
810 error.name = 'MongoError';
820 throw error;
83 }
84 }
85
86 // Check special case where we are using an objectId
870 if(selector instanceof ObjectID || (selector != null && selector._bsontype == 'ObjectID')) {
880 selector = {_id:selector};
89 }
90
91 // If it's a serialized fields field we need to just let it through
92 // user be warned it better be good
930 if(options && options.fields && !(Buffer.isBuffer(options.fields))) {
940 fields = {};
95
960 if(Array.isArray(options.fields)) {
970 if(!options.fields.length) {
980 fields['_id'] = 1;
99 } else {
1000 for (var i = 0, l = options.fields.length; i < l; i++) {
1010 fields[options.fields[i]] = 1;
102 }
103 }
104 } else {
1050 fields = options.fields;
106 }
107 }
108
1090 if (!options) options = {};
1100 options.skip = len > 3 ? args[2] : options.skip ? options.skip : 0;
1110 options.limit = len > 3 ? args[3] : options.limit ? options.limit : 0;
1120 options.raw = options.raw != null && typeof options.raw === 'boolean' ? options.raw : this.raw;
1130 options.hint = options.hint != null ? shared.normalizeHintField(options.hint) : this.internalHint;
1140 options.timeout = len == 5 ? args[4] : typeof options.timeout === 'undefined' ? undefined : options.timeout;
115 // If we have overridden slaveOk otherwise use the default db setting
1160 options.slaveOk = options.slaveOk != null ? options.slaveOk : this.db.slaveOk;
117
118 // Set option
1190 var o = options;
120 // Support read/readPreference
1210 if(o["read"] != null) o["readPreference"] = o["read"];
122 // Set the read preference
1230 o.read = o["readPreference"] ? o.readPreference : this.readPreference;
124 // Adjust slave ok if read preference is secondary or secondary only
1250 if(o.read == "secondary" || o.read == "secondaryOnly") options.slaveOk = true;
126
127 // Set the selector
1280 o.selector = selector;
129
130 // Create precursor
1310 var scope = new Scope(this, {}, fields, o);
132 // Callback for backward compatibility
1330 if(callback) return callback(null, scope.find(selector));
134 // Return the pre cursor object
1350 return scope.find(selector);
136};
137
1381var findOne = function findOne () {
1390 var self = this;
1400 var args = Array.prototype.slice.call(arguments, 0);
1410 var callback = args.pop();
1420 var cursor = this.find.apply(this, args).limit(-1).batchSize(1);
143
144 // Return the item
1450 cursor.nextObject(function(err, item) {
1460 if(err != null) return callback(utils.toError(err), null);
1470 callback(null, item);
148 });
149};
150
151
1521exports.find = find;
1531exports.findOne = findOne;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/collection/shared.js

16%
65
11
54
LineHitsSource
1// ***************************************************
2// Write concerns
3// ***************************************************
41var _hasWriteConcern = function(errorOptions) {
50 return errorOptions == true
6 || errorOptions.w > 0
7 || errorOptions.w == 'majority'
8 || errorOptions.j == true
9 || errorOptions.journal == true
10 || errorOptions.fsync == true
11}
12
131var _setWriteConcernHash = function(options) {
140 var finalOptions = {};
150 if(options.w != null) finalOptions.w = options.w;
160 if(options.journal == true) finalOptions.j = options.journal;
170 if(options.j == true) finalOptions.j = options.j;
180 if(options.fsync == true) finalOptions.fsync = options.fsync;
190 if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout;
200 return finalOptions;
21}
22
231var _getWriteConcern = function(self, options) {
24 // Final options
250 var finalOptions = {w:1};
26 // Local options verification
270 if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') {
280 finalOptions = _setWriteConcernHash(options);
290 } else if(typeof options.safe == "boolean") {
300 finalOptions = {w: (options.safe ? 1 : 0)};
310 } else if(options.safe != null && typeof options.safe == 'object') {
320 finalOptions = _setWriteConcernHash(options.safe);
330 } else if(self.opts.w != null || typeof self.opts.j == 'boolean' || typeof self.opts.journal == 'boolean' || typeof self.opts.fsync == 'boolean') {
340 finalOptions = _setWriteConcernHash(self.opts);
350 } else if(typeof self.opts.safe == "boolean") {
360 finalOptions = {w: (self.opts.safe ? 1 : 0)};
370 } else if(self.db.safe.w != null || typeof self.db.safe.j == 'boolean' || typeof self.db.safe.journal == 'boolean' || typeof self.db.safe.fsync == 'boolean') {
380 finalOptions = _setWriteConcernHash(self.db.safe);
390 } else if(self.db.options.w != null || typeof self.db.options.j == 'boolean' || typeof self.db.options.journal == 'boolean' || typeof self.db.options.fsync == 'boolean') {
400 finalOptions = _setWriteConcernHash(self.db.options);
410 } else if(typeof self.db.safe == "boolean") {
420 finalOptions = {w: (self.db.safe ? 1 : 0)};
43 }
44
45 // Ensure we don't have an invalid combination of write concerns
460 if(finalOptions.w < 1
470 && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowlegement using w < 1 cannot be combined with journal:true or fsync:true");
48
49 // Return the options
500 return finalOptions;
51}
52
531var _getReadConcern = function(self, options) {
540 if(options.readPreference) return options.readPreference;
550 if(self.readPreference) return self.readPreference;
560 if(self.db.readPreference) return self.readPreference;
570 return 'primary';
58}
59
60/**
61 * @ignore
62 */
631var checkCollectionName = function checkCollectionName (collectionName) {
640 if('string' !== typeof collectionName) {
650 throw Error("collection name must be a String");
66 }
67
680 if(!collectionName || collectionName.indexOf('..') != -1) {
690 throw Error("collection names cannot be empty");
70 }
71
720 if(collectionName.indexOf('$') != -1 &&
73 collectionName.match(/((^\$cmd)|(oplog\.\$main))/) == null) {
740 throw Error("collection names must not contain '$'");
75 }
76
770 if(collectionName.match(/^\.|\.$/) != null) {
780 throw Error("collection names must not start or end with '.'");
79 }
80
81 // Validate that we are not passing 0x00 in the colletion name
820 if(!!~collectionName.indexOf("\x00")) {
830 throw new Error("collection names cannot contain a null character");
84 }
85};
86
87
88/**
89 * Normalizes a `hint` argument.
90 *
91 * @param {String|Object|Array} hint
92 * @return {Object}
93 * @api private
94 */
951var normalizeHintField = function normalizeHintField(hint) {
960 var finalHint = null;
97
980 if(typeof hint == 'string') {
990 finalHint = hint;
1000 } else if(Array.isArray(hint)) {
1010 finalHint = {};
102
1030 hint.forEach(function(param) {
1040 finalHint[param] = 1;
105 });
1060 } else if(hint != null && typeof hint == 'object') {
1070 finalHint = {};
1080 for (var name in hint) {
1090 finalHint[name] = hint[name];
110 }
111 }
112
1130 return finalHint;
114};
115
1161exports._getWriteConcern = _getWriteConcern;
1171exports._hasWriteConcern = _hasWriteConcern;
1181exports._getReadConcern = _getReadConcern;
1191exports.checkCollectionName = checkCollectionName;
1201exports.normalizeHintField = normalizeHintField;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/command_cursor.js

2%
142
3
139
LineHitsSource
11var Long = require('bson').Long
2 , GetMoreCommand = require('./commands/get_more_command').GetMoreCommand;
3
41var CommandCursor = function(db, collection, command, options) {
5 // Ensure empty options if no options passed
60 options = options || {};
7
8 // Default cursor id is 0
90 var cursorId = Long.fromInt(0);
100 var zeroCursor = Long.fromInt(0);
110 var state = 'init';
12
13 // Hardcode batch size
140 command.cursor.batchSize = 1;
15
16 // BatchSize
170 var batchSize = command.cursor.batchSize || 0;
180 var raw = options.raw || false;
190 var readPreference = options.readPreference || 'primary';
20
21 // Checkout a connection
220 var connection = db.serverConfig.checkoutReader(readPreference);
23 // MaxTimeMS
240 var maxTimeMS = options.maxTimeMS;
25
26 // Contains all the items
270 var items = null;
28
29 // Execute getmore
300 var getMore = function(callback) {
31 // Resolve more of the cursor using the getMore command
320 var getMoreCommand = new GetMoreCommand(db
33 , db.databaseName + "." + collection.collectionName
34 , batchSize
35 , cursorId
36 );
37
38 // Set up options
390 var command_options = { connection:connection };
40
41 // Execute the getMore Command
420 db._executeQueryCommand(getMoreCommand, command_options, function(err, result) {
430 if(err) {
440 items = [];
450 state = 'closed';
460 return callback(err);
47 }
48
49 // Return all the documents
500 callback(null, result);
51 });
52 }
53
540 var exhaustGetMore = function(callback) {
550 getMore(function(err, result) {
560 if(err) {
570 items = [];
580 state = 'closed';
590 return callback(err, null);
60 }
61
62 // Add the items
630 items = items.concat(result.documents);
64
65 // Set the cursor id
660 cursorId = result.cursorId;
670 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
68
69 // If the cursor is done
700 if(result.cursorId.equals(zeroCursor)) {
710 return callback(null, items);
72 }
73
74 // Check the cursor id
750 exhaustGetMore(callback);
76 });
77 }
78
790 var exhaustGetMoreEach = function(callback) {
800 getMore(function(err, result) {
810 if(err) {
820 items = [];
830 state = 'closed';
840 return callback(err, null);
85 }
86
87 // Add the items
880 items = result.documents;
89
90 // Emit all the items in the first batch
910 while(items.length > 0) {
920 callback(null, items.shift());
93 }
94
95 // Set the cursor id
960 cursorId = result.cursorId;
970 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
98
99 // If the cursor is done
1000 if(result.cursorId.equals(zeroCursor)) {
1010 state = "closed";
1020 return callback(null, null);
103 }
104
105 // Check the cursor id
1060 exhaustGetMoreEach(callback);
107 });
108 }
109
110 //
111 // Get all the elements
112 //
1130 this.get = function(options, callback) {
1140 if(typeof options == 'function') {
1150 callback = options;
1160 options = {};
117 }
118
119 // Set the connection to the passed in one if it's provided
1200 connection = options.connection ? options.connection : connection;
121
122 // Command options
1230 var _options = {connection:connection};
1240 if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS;
125
126 // Execute the internal command first
1270 db.command(command, _options, function(err, result) {
1280 if(err) {
1290 state = 'closed';
1300 return callback(err, null);
131 }
132
133 // Retrieve the cursor id
1340 cursorId = result.cursor.id;
1350 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
136
137 // Validate cursorId
1380 if(cursorId.equals(zeroCursor)) {
1390 return callback(null, result.cursor.firstBatch);
140 };
141
142 // Add to the items
1430 items = result.cursor.firstBatch;
144 // Execute the getMore
1450 exhaustGetMore(callback);
146 });
147 }
148
149 //
150 // Iterate over all the items
151 //
1520 this.each = function(options, callback) {
1530 if(typeof options == 'function') {
1540 callback = options;
1550 options = {};
156 }
157
158 // If it's a closed cursor return error
1590 if(this.isClosed()) return callback(new Error("cursor is closed"));
160 // Set the connection to the passed in one if it's provided
1610 connection = options.connection ? options.connection : connection;
162
163 // Command options
1640 var _options = {connection:connection};
1650 if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS;
166
167 // Execute the internal command first
1680 db.command(command, _options, function(err, result) {
1690 if(err) {
1700 state = 'closed';
1710 return callback(err, null);
172 }
173
174 // Get all the items
1750 items = result.cursor.firstBatch;
176
177 // Emit all the items in the first batch
1780 while(items.length > 0) {
1790 callback(null, items.shift());
180 }
181
182 // Retrieve the cursor id
1830 cursorId = result.cursor.id;
1840 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
185
186 // If no cursor we just finish up the current batch of items
1870 if(cursorId.equals(zeroCursor)) {
1880 state = 'closed';
1890 return callback(null, null);
190 }
191
192 // Emit each until no more getMore's
1930 exhaustGetMoreEach(callback);
194 });
195 }
196
197 //
198 // Get the next object
199 //
2000 this.next = function(options, callback) {
2010 if(typeof options == 'function') {
2020 callback = options;
2030 options = {};
204 }
205
206 // If it's a closed cursor return error
2070 if(this.isClosed()) return callback(new Error("cursor is closed"));
208
209 // Set the connection to the passed in one if it's provided
2100 connection = options.connection ? options.connection : connection;
211
212 // Command options
2130 var _options = {connection:connection};
2140 if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS;
215
216 // Execute the internal command first
2170 if(!items) {
2180 db.command(command, _options, function(err, result) {
2190 if(err) {
2200 state = 'closed';
2210 return callback(err, null);
222 }
223
224 // Retrieve the cursor id
2250 cursorId = result.cursor.id;
2260 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
227 // Get the first batch results
2280 items = result.cursor.firstBatch;
229 // We have items return the first one
2300 if(items.length > 0) {
2310 callback(null, items.shift());
232 } else {
2330 state = 'closed';
2340 callback(null, null);
235 }
236 });
2370 } else if(items.length > 0) {
2380 callback(null, items.shift());
2390 } else if(items.length == 0 && cursorId.equals(zeroCursor)) {
2400 state = 'closed';
2410 callback(null, null);
242 } else {
243 // Execute a getMore
2440 getMore(function(err, result) {
2450 if(err) {
2460 state = 'closed';
2470 return callback(err, null);
248 }
249
250 // Set the cursor id
2510 cursorId = result.cursorId;
2520 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
253
254 // Add the items
2550 items = items.concat(result.documents);
256 // If no more items
2570 if(items.length == 0) {
2580 state = 'closed';
2590 return callback(null, null);
260 }
261
262 // Return the item
2630 return callback(null, items.shift());
264 })
265 }
266 }
267
268 // Validate if the cursor is closed
2690 this.isClosed = function() {
2700 return state == 'closed';
271 }
272
273 // Allow us to set the MaxTimeMS
2740 this.maxTimeMS = function(_maxTimeMS) {
2750 maxTimeMS = _maxTimeMS;
276 }
277
278 // Close the cursor sending a kill cursor command if needed
2790 this.close = function(options, callback) {
2800 if(typeof options == 'function') {
2810 callback = options;
2820 options = {};
283 }
284
285 // Close the cursor if not needed
2860 if(cursorId instanceof Long && cursorId.greaterThan(Long.fromInt(0))) {
2870 try {
2880 var command = new KillCursorCommand(this.db, [cursorId]);
289 // Added an empty callback to ensure we don't throw any null exceptions
2900 db._executeQueryCommand(command, {connection:connection});
291 } catch(err) {}
292 }
293
294 // Null out the connection
2950 connection = null;
296 // Reset cursor id
2970 cursorId = Long.fromInt(0);
298 // Set to closed status
2990 state = 'closed';
300 // Clear out all the items
3010 items = null;
302
3030 if(callback) {
3040 callback(null, null);
305 }
306 }
307}
308
3091exports.CommandCursor = CommandCursor;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/commands/base_command.js

77%
18
14
4
LineHitsSource
1/**
2 Base object used for common functionality
3**/
41var BaseCommand = exports.BaseCommand = function BaseCommand() {
5};
6
71var id = 1;
81BaseCommand.prototype.getRequestId = function getRequestId() {
90 if (!this.requestId) this.requestId = id++;
100 return this.requestId;
11};
12
131BaseCommand.prototype.setMongosReadPreference = function setMongosReadPreference(readPreference, tags) {}
14
151BaseCommand.prototype.updateRequestId = function() {
160 this.requestId = id++;
170 return this.requestId;
18};
19
20// OpCodes
211BaseCommand.OP_REPLY = 1;
221BaseCommand.OP_MSG = 1000;
231BaseCommand.OP_UPDATE = 2001;
241BaseCommand.OP_INSERT = 2002;
251BaseCommand.OP_GET_BY_OID = 2003;
261BaseCommand.OP_QUERY = 2004;
271BaseCommand.OP_GET_MORE = 2005;
281BaseCommand.OP_DELETE = 2006;
291BaseCommand.OP_KILL_CURSORS = 2007;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/commands/db_command.js

24%
128
31
97
LineHitsSource
11var QueryCommand = require('./query_command').QueryCommand,
2 InsertCommand = require('./insert_command').InsertCommand,
3 inherits = require('util').inherits,
4 utils = require('../utils'),
5 crypto = require('crypto');
6
7/**
8 Db Command
9**/
101var DbCommand = exports.DbCommand = function(dbInstance, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) {
110 QueryCommand.call(this);
120 this.collectionName = collectionName;
130 this.queryOptions = queryOptions;
140 this.numberToSkip = numberToSkip;
150 this.numberToReturn = numberToReturn;
160 this.query = query;
170 this.returnFieldSelector = returnFieldSelector;
180 this.db = dbInstance;
19
20 // Set the slave ok bit
210 if(this.db && this.db.slaveOk) {
220 this.queryOptions |= QueryCommand.OPTS_SLAVE;
23 }
24
25 // Make sure we don't get a null exception
260 options = options == null ? {} : options;
27
28 // Allow for overriding the BSON checkKeys function
290 this.checkKeys = typeof options['checkKeys'] == 'boolean' ? options["checkKeys"] : true;
30
31 // Let us defined on a command basis if we want functions to be serialized or not
320 if(options['serializeFunctions'] != null && options['serializeFunctions']) {
330 this.serializeFunctions = true;
34 }
35};
36
371inherits(DbCommand, QueryCommand);
38
39// Constants
401DbCommand.SYSTEM_NAMESPACE_COLLECTION = "system.namespaces";
411DbCommand.SYSTEM_INDEX_COLLECTION = "system.indexes";
421DbCommand.SYSTEM_PROFILE_COLLECTION = "system.profile";
431DbCommand.SYSTEM_USER_COLLECTION = "system.users";
441DbCommand.SYSTEM_COMMAND_COLLECTION = "$cmd";
451DbCommand.SYSTEM_JS_COLLECTION = "system.js";
46
47// New commands
481DbCommand.NcreateIsMasterCommand = function(db, databaseName) {
490 return new DbCommand(db, databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null);
50};
51
52// Provide constructors for different db commands
531DbCommand.createIsMasterCommand = function(db) {
540 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null);
55};
56
571DbCommand.createCollectionInfoCommand = function(db, selector) {
580 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_NAMESPACE_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, 0, selector, null);
59};
60
611DbCommand.createGetNonceCommand = function(db, options) {
620 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'getnonce':1}, null);
63};
64
651DbCommand.createAuthenticationCommand = function(db, username, password, nonce, authdb) {
66 // Use node md5 generator
670 var md5 = crypto.createHash('md5');
68 // Generate keys used for authentication
690 md5.update(username + ":mongo:" + password);
700 var hash_password = md5.digest('hex');
71 // Final key
720 md5 = crypto.createHash('md5');
730 md5.update(nonce + username + hash_password);
740 var key = md5.digest('hex');
75 // Creat selector
760 var selector = {'authenticate':1, 'user':username, 'nonce':nonce, 'key':key};
77 // Create db command
780 return new DbCommand(db, authdb + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NONE, 0, -1, selector, null);
79};
80
811DbCommand.createLogoutCommand = function(db) {
820 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'logout':1}, null);
83};
84
851DbCommand.createCreateCollectionCommand = function(db, collectionName, options) {
860 var selector = {'create':collectionName};
87 // Modify the options to ensure correct behaviour
880 for(var name in options) {
890 if(options[name] != null && options[name].constructor != Function) selector[name] = options[name];
90 }
91 // Execute the command
920 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, selector, null);
93};
94
951DbCommand.createDropCollectionCommand = function(db, collectionName) {
960 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'drop':collectionName}, null);
97};
98
991DbCommand.createRenameCollectionCommand = function(db, fromCollectionName, toCollectionName, options) {
1000 var renameCollection = db.databaseName + "." + fromCollectionName;
1010 var toCollection = db.databaseName + "." + toCollectionName;
1020 var dropTarget = options && options.dropTarget ? options.dropTarget : false;
1030 return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'renameCollection':renameCollection, 'to':toCollection, 'dropTarget':dropTarget}, null);
104};
105
1061DbCommand.createGetLastErrorCommand = function(options, db) {
107
1080 if (typeof db === 'undefined') {
1090 db = options;
1100 options = {};
111 }
112 // Final command
1130 var command = {'getlasterror':1};
114 // If we have an options Object let's merge in the fields (fsync/wtimeout/w)
1150 if('object' === typeof options) {
1160 for(var name in options) {
1170 command[name] = options[name]
118 }
119 }
120
121 // Special case for w == 1, remove the w
1220 if(1 == command.w) {
1230 delete command.w;
124 }
125
126 // Execute command
1270 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command, null);
128};
129
1301DbCommand.createGetLastStatusCommand = DbCommand.createGetLastErrorCommand;
131
1321DbCommand.createGetPreviousErrorsCommand = function(db) {
1330 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'getpreverror':1}, null);
134};
135
1361DbCommand.createResetErrorHistoryCommand = function(db) {
1370 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'reseterror':1}, null);
138};
139
1401DbCommand.createCreateIndexCommand = function(db, collectionName, fieldOrSpec, options) {
1410 var fieldHash = {};
1420 var indexes = [];
1430 var keys;
144
145 // Get all the fields accordingly
1460 if('string' == typeof fieldOrSpec) {
147 // 'type'
1480 indexes.push(fieldOrSpec + '_' + 1);
1490 fieldHash[fieldOrSpec] = 1;
150
1510 } else if(utils.isArray(fieldOrSpec)) {
152
1530 fieldOrSpec.forEach(function(f) {
1540 if('string' == typeof f) {
155 // [{location:'2d'}, 'type']
1560 indexes.push(f + '_' + 1);
1570 fieldHash[f] = 1;
1580 } else if(utils.isArray(f)) {
159 // [['location', '2d'],['type', 1]]
1600 indexes.push(f[0] + '_' + (f[1] || 1));
1610 fieldHash[f[0]] = f[1] || 1;
1620 } else if(utils.isObject(f)) {
163 // [{location:'2d'}, {type:1}]
1640 keys = Object.keys(f);
1650 keys.forEach(function(k) {
1660 indexes.push(k + '_' + f[k]);
1670 fieldHash[k] = f[k];
168 });
169 } else {
170 // undefined (ignore)
171 }
172 });
173
1740 } else if(utils.isObject(fieldOrSpec)) {
175 // {location:'2d', type:1}
1760 keys = Object.keys(fieldOrSpec);
1770 keys.forEach(function(key) {
1780 indexes.push(key + '_' + fieldOrSpec[key]);
1790 fieldHash[key] = fieldOrSpec[key];
180 });
181 }
182
183 // Generate the index name
1840 var indexName = typeof options.name == 'string'
185 ? options.name
186 : indexes.join("_");
187
1880 var selector = {
189 'ns': db.databaseName + "." + collectionName,
190 'key': fieldHash,
191 'name': indexName
192 }
193
194 // Ensure we have a correct finalUnique
1950 var finalUnique = options == null || 'object' === typeof options
196 ? false
197 : options;
198
199 // Set up options
2000 options = options == null || typeof options == 'boolean'
201 ? {}
202 : options;
203
204 // Add all the options
2050 var keys = Object.keys(options);
2060 for(var i = 0; i < keys.length; i++) {
2070 selector[keys[i]] = options[keys[i]];
208 }
209
2100 if(selector['unique'] == null)
2110 selector['unique'] = finalUnique;
212
2130 var name = db.databaseName + "." + DbCommand.SYSTEM_INDEX_COLLECTION;
2140 var cmd = new InsertCommand(db, name, false);
2150 return cmd.add(selector);
216};
217
2181DbCommand.logoutCommand = function(db, command_hash, options) {
2190 var dbName = options != null && options['authdb'] != null ? options['authdb'] : db.databaseName;
2200 return new DbCommand(db, dbName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null);
221}
222
2231DbCommand.createDropIndexCommand = function(db, collectionName, indexName) {
2240 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'deleteIndexes':collectionName, 'index':indexName}, null);
225};
226
2271DbCommand.createReIndexCommand = function(db, collectionName) {
2280 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'reIndex':collectionName}, null);
229};
230
2311DbCommand.createDropDatabaseCommand = function(db) {
2320 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'dropDatabase':1}, null);
233};
234
2351DbCommand.createDbCommand = function(db, command_hash, options, auth_db) {
2360 var db_name = (auth_db ? auth_db : db.databaseName) + "." + DbCommand.SYSTEM_COMMAND_COLLECTION;
2370 options = options == null ? {checkKeys: false} : options;
2380 return new DbCommand(db, db_name, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null, options);
239};
240
2411DbCommand.createAdminDbCommand = function(db, command_hash) {
2420 return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null);
243};
244
2451DbCommand.createAdminDbCommandSlaveOk = function(db, command_hash) {
2460 return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null);
247};
248
2491DbCommand.createDbSlaveOkCommand = function(db, command_hash, options) {
2500 options = options == null ? {checkKeys: false} : options;
2510 var dbName = options.dbName ? options.dbName : db.databaseName;
2520 return new DbCommand(db, dbName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null, options);
253};
254

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/commands/delete_command.js

7%
68
5
63
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits;
3
4/**
5 Insert Document Command
6**/
71var DeleteCommand = exports.DeleteCommand = function(db, collectionName, selector, flags) {
80 BaseCommand.call(this);
9
10 // Validate correctness off the selector
110 var object = selector;
120 if(Buffer.isBuffer(object)) {
130 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
140 if(object_size != object.length) {
150 var error = new Error("delete raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
160 error.name = 'MongoError';
170 throw error;
18 }
19 }
20
210 this.flags = flags;
220 this.collectionName = collectionName;
230 this.selector = selector;
240 this.db = db;
25};
26
271inherits(DeleteCommand, BaseCommand);
28
291DeleteCommand.OP_DELETE = 2006;
30
31/*
32struct {
33 MsgHeader header; // standard message header
34 int32 ZERO; // 0 - reserved for future use
35 cstring fullCollectionName; // "dbname.collectionname"
36 int32 ZERO; // 0 - reserved for future use
37 mongo.BSON selector; // query object. See below for details.
38}
39*/
401DeleteCommand.prototype.toBinary = function(bsonSettings) {
41 // Validate that we are not passing 0x00 in the colletion name
420 if(!!~this.collectionName.indexOf("\x00")) {
430 throw new Error("namespace cannot contain a null character");
44 }
45
46 // Calculate total length of the document
470 var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.selector, false, true) + (4 * 4);
48
49 // Enforce maximum bson size
500 if(!bsonSettings.disableDriverBSONSizeCheck
51 && totalLengthOfCommand > bsonSettings.maxBsonSize)
520 throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
53
540 if(bsonSettings.disableDriverBSONSizeCheck
55 && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
560 throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
57
58 // Let's build the single pass buffer command
590 var _index = 0;
600 var _command = new Buffer(totalLengthOfCommand);
61 // Write the header information to the buffer
620 _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
630 _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
640 _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
650 _command[_index] = totalLengthOfCommand & 0xff;
66 // Adjust index
670 _index = _index + 4;
68 // Write the request ID
690 _command[_index + 3] = (this.requestId >> 24) & 0xff;
700 _command[_index + 2] = (this.requestId >> 16) & 0xff;
710 _command[_index + 1] = (this.requestId >> 8) & 0xff;
720 _command[_index] = this.requestId & 0xff;
73 // Adjust index
740 _index = _index + 4;
75 // Write zero
760 _command[_index++] = 0;
770 _command[_index++] = 0;
780 _command[_index++] = 0;
790 _command[_index++] = 0;
80 // Write the op_code for the command
810 _command[_index + 3] = (DeleteCommand.OP_DELETE >> 24) & 0xff;
820 _command[_index + 2] = (DeleteCommand.OP_DELETE >> 16) & 0xff;
830 _command[_index + 1] = (DeleteCommand.OP_DELETE >> 8) & 0xff;
840 _command[_index] = DeleteCommand.OP_DELETE & 0xff;
85 // Adjust index
860 _index = _index + 4;
87
88 // Write zero
890 _command[_index++] = 0;
900 _command[_index++] = 0;
910 _command[_index++] = 0;
920 _command[_index++] = 0;
93
94 // Write the collection name to the command
950 _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
960 _command[_index - 1] = 0;
97
98 // Write the flags
990 _command[_index + 3] = (this.flags >> 24) & 0xff;
1000 _command[_index + 2] = (this.flags >> 16) & 0xff;
1010 _command[_index + 1] = (this.flags >> 8) & 0xff;
1020 _command[_index] = this.flags & 0xff;
103 // Adjust index
1040 _index = _index + 4;
105
106 // Document binary length
1070 var documentLength = 0
108
109 // Serialize the selector
110 // If we are passing a raw buffer, do minimal validation
1110 if(Buffer.isBuffer(this.selector)) {
1120 documentLength = this.selector.length;
113 // Copy the data into the current buffer
1140 this.selector.copy(_command, _index);
115 } else {
1160 documentLength = this.db.bson.serializeWithBufferAndIndex(this.selector, false, _command, _index) - _index + 1;
117 }
118
119 // Write the length to the document
1200 _command[_index + 3] = (documentLength >> 24) & 0xff;
1210 _command[_index + 2] = (documentLength >> 16) & 0xff;
1220 _command[_index + 1] = (documentLength >> 8) & 0xff;
1230 _command[_index] = documentLength & 0xff;
124 // Update index in buffer
1250 _index = _index + documentLength;
126 // Add terminating 0 for the object
1270 _command[_index - 1] = 0;
1280 return _command;
129};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/commands/get_more_command.js

9%
52
5
47
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits,
3 binaryutils = require('../utils');
4
5/**
6 Get More Document Command
7**/
81var GetMoreCommand = exports.GetMoreCommand = function(db, collectionName, numberToReturn, cursorId) {
90 BaseCommand.call(this);
10
110 this.collectionName = collectionName;
120 this.numberToReturn = numberToReturn;
130 this.cursorId = cursorId;
140 this.db = db;
15};
16
171inherits(GetMoreCommand, BaseCommand);
18
191GetMoreCommand.OP_GET_MORE = 2005;
20
211GetMoreCommand.prototype.toBinary = function() {
22 // Validate that we are not passing 0x00 in the colletion name
230 if(!!~this.collectionName.indexOf("\x00")) {
240 throw new Error("namespace cannot contain a null character");
25 }
26
27 // Calculate total length of the document
280 var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 8 + (4 * 4);
29 // Let's build the single pass buffer command
300 var _index = 0;
310 var _command = new Buffer(totalLengthOfCommand);
32 // Write the header information to the buffer
330 _command[_index++] = totalLengthOfCommand & 0xff;
340 _command[_index++] = (totalLengthOfCommand >> 8) & 0xff;
350 _command[_index++] = (totalLengthOfCommand >> 16) & 0xff;
360 _command[_index++] = (totalLengthOfCommand >> 24) & 0xff;
37
38 // Write the request ID
390 _command[_index++] = this.requestId & 0xff;
400 _command[_index++] = (this.requestId >> 8) & 0xff;
410 _command[_index++] = (this.requestId >> 16) & 0xff;
420 _command[_index++] = (this.requestId >> 24) & 0xff;
43
44 // Write zero
450 _command[_index++] = 0;
460 _command[_index++] = 0;
470 _command[_index++] = 0;
480 _command[_index++] = 0;
49
50 // Write the op_code for the command
510 _command[_index++] = GetMoreCommand.OP_GET_MORE & 0xff;
520 _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 8) & 0xff;
530 _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 16) & 0xff;
540 _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 24) & 0xff;
55
56 // Write zero
570 _command[_index++] = 0;
580 _command[_index++] = 0;
590 _command[_index++] = 0;
600 _command[_index++] = 0;
61
62 // Write the collection name to the command
630 _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
640 _command[_index - 1] = 0;
65
66 // Number of documents to return
670 _command[_index++] = this.numberToReturn & 0xff;
680 _command[_index++] = (this.numberToReturn >> 8) & 0xff;
690 _command[_index++] = (this.numberToReturn >> 16) & 0xff;
700 _command[_index++] = (this.numberToReturn >> 24) & 0xff;
71
72 // Encode the cursor id
730 var low_bits = this.cursorId.getLowBits();
74 // Encode low bits
750 _command[_index++] = low_bits & 0xff;
760 _command[_index++] = (low_bits >> 8) & 0xff;
770 _command[_index++] = (low_bits >> 16) & 0xff;
780 _command[_index++] = (low_bits >> 24) & 0xff;
79
800 var high_bits = this.cursorId.getHighBits();
81 // Encode high bits
820 _command[_index++] = high_bits & 0xff;
830 _command[_index++] = (high_bits >> 8) & 0xff;
840 _command[_index++] = (high_bits >> 16) & 0xff;
850 _command[_index++] = (high_bits >> 24) & 0xff;
86 // Return command
870 return _command;
88};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/commands/insert_command.js

7%
81
6
75
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits;
3
4/**
5 Insert Document Command
6**/
71var InsertCommand = exports.InsertCommand = function(db, collectionName, checkKeys, options) {
80 BaseCommand.call(this);
9
100 this.collectionName = collectionName;
110 this.documents = [];
120 this.checkKeys = checkKeys == null ? true : checkKeys;
130 this.db = db;
140 this.flags = 0;
150 this.serializeFunctions = false;
16
17 // Ensure valid options hash
180 options = options == null ? {} : options;
19
20 // Check if we have keepGoing set -> set flag if it's the case
210 if(options['keepGoing'] != null && options['keepGoing']) {
22 // This will finish inserting all non-index violating documents even if it returns an error
230 this.flags = 1;
24 }
25
26 // Check if we have keepGoing set -> set flag if it's the case
270 if(options['continueOnError'] != null && options['continueOnError']) {
28 // This will finish inserting all non-index violating documents even if it returns an error
290 this.flags = 1;
30 }
31
32 // Let us defined on a command basis if we want functions to be serialized or not
330 if(options['serializeFunctions'] != null && options['serializeFunctions']) {
340 this.serializeFunctions = true;
35 }
36};
37
381inherits(InsertCommand, BaseCommand);
39
40// OpCodes
411InsertCommand.OP_INSERT = 2002;
42
431InsertCommand.prototype.add = function(document) {
440 if(Buffer.isBuffer(document)) {
450 var object_size = document[0] | document[1] << 8 | document[2] << 16 | document[3] << 24;
460 if(object_size != document.length) {
470 var error = new Error("insert raw message size does not match message header size [" + document.length + "] != [" + object_size + "]");
480 error.name = 'MongoError';
490 throw error;
50 }
51 }
52
530 this.documents.push(document);
540 return this;
55};
56
57/*
58struct {
59 MsgHeader header; // standard message header
60 int32 ZERO; // 0 - reserved for future use
61 cstring fullCollectionName; // "dbname.collectionname"
62 BSON[] documents; // one or more documents to insert into the collection
63}
64*/
651InsertCommand.prototype.toBinary = function(bsonSettings) {
66 // Validate that we are not passing 0x00 in the colletion name
670 if(!!~this.collectionName.indexOf("\x00")) {
680 throw new Error("namespace cannot contain a null character");
69 }
70
71 // Calculate total length of the document
720 var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + (4 * 4);
73 // var docLength = 0
740 for(var i = 0; i < this.documents.length; i++) {
750 if(Buffer.isBuffer(this.documents[i])) {
760 totalLengthOfCommand += this.documents[i].length;
77 } else {
78 // Calculate size of document
790 totalLengthOfCommand += this.db.bson.calculateObjectSize(this.documents[i], this.serializeFunctions, true);
80 }
81 }
82
83 // Enforce maximum bson size
840 if(!bsonSettings.disableDriverBSONSizeCheck
85 && totalLengthOfCommand > bsonSettings.maxBsonSize)
860 throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
87
880 if(bsonSettings.disableDriverBSONSizeCheck
89 && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
900 throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
91
92 // Let's build the single pass buffer command
930 var _index = 0;
940 var _command = new Buffer(totalLengthOfCommand);
95 // Write the header information to the buffer
960 _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
970 _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
980 _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
990 _command[_index] = totalLengthOfCommand & 0xff;
100 // Adjust index
1010 _index = _index + 4;
102 // Write the request ID
1030 _command[_index + 3] = (this.requestId >> 24) & 0xff;
1040 _command[_index + 2] = (this.requestId >> 16) & 0xff;
1050 _command[_index + 1] = (this.requestId >> 8) & 0xff;
1060 _command[_index] = this.requestId & 0xff;
107 // Adjust index
1080 _index = _index + 4;
109 // Write zero
1100 _command[_index++] = 0;
1110 _command[_index++] = 0;
1120 _command[_index++] = 0;
1130 _command[_index++] = 0;
114 // Write the op_code for the command
1150 _command[_index + 3] = (InsertCommand.OP_INSERT >> 24) & 0xff;
1160 _command[_index + 2] = (InsertCommand.OP_INSERT >> 16) & 0xff;
1170 _command[_index + 1] = (InsertCommand.OP_INSERT >> 8) & 0xff;
1180 _command[_index] = InsertCommand.OP_INSERT & 0xff;
119 // Adjust index
1200 _index = _index + 4;
121 // Write flags if any
1220 _command[_index + 3] = (this.flags >> 24) & 0xff;
1230 _command[_index + 2] = (this.flags >> 16) & 0xff;
1240 _command[_index + 1] = (this.flags >> 8) & 0xff;
1250 _command[_index] = this.flags & 0xff;
126 // Adjust index
1270 _index = _index + 4;
128 // Write the collection name to the command
1290 _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
1300 _command[_index - 1] = 0;
131
132 // Write all the bson documents to the buffer at the index offset
1330 for(var i = 0; i < this.documents.length; i++) {
134 // Document binary length
1350 var documentLength = 0
1360 var object = this.documents[i];
137
138 // Serialize the selector
139 // If we are passing a raw buffer, do minimal validation
1400 if(Buffer.isBuffer(object)) {
1410 documentLength = object.length;
142 // Copy the data into the current buffer
1430 object.copy(_command, _index);
144 } else {
145 // Serialize the document straight to the buffer
1460 documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1;
147 }
148
149 // Write the length to the document
1500 _command[_index + 3] = (documentLength >> 24) & 0xff;
1510 _command[_index + 2] = (documentLength >> 16) & 0xff;
1520 _command[_index + 1] = (documentLength >> 8) & 0xff;
1530 _command[_index] = documentLength & 0xff;
154 // Update index in buffer
1550 _index = _index + documentLength;
156 // Add terminating 0 for the object
1570 _command[_index - 1] = 0;
158 }
159
1600 return _command;
161};
162

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js

9%
54
5
49
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits,
3 binaryutils = require('../utils');
4
5/**
6 Insert Document Command
7**/
81var KillCursorCommand = exports.KillCursorCommand = function(db, cursorIds) {
90 BaseCommand.call(this);
10
110 this.cursorIds = cursorIds;
120 this.db = db;
13};
14
151inherits(KillCursorCommand, BaseCommand);
16
171KillCursorCommand.OP_KILL_CURSORS = 2007;
18
19/*
20struct {
21 MsgHeader header; // standard message header
22 int32 ZERO; // 0 - reserved for future use
23 int32 numberOfCursorIDs; // number of cursorIDs in message
24 int64[] cursorIDs; // array of cursorIDs to close
25}
26*/
271KillCursorCommand.prototype.toBinary = function() {
28 // Calculate total length of the document
290 var totalLengthOfCommand = 4 + 4 + (4 * 4) + (this.cursorIds.length * 8);
30 // Let's build the single pass buffer command
310 var _index = 0;
320 var _command = new Buffer(totalLengthOfCommand);
33 // Write the header information to the buffer
340 _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
350 _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
360 _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
370 _command[_index] = totalLengthOfCommand & 0xff;
38 // Adjust index
390 _index = _index + 4;
40 // Write the request ID
410 _command[_index + 3] = (this.requestId >> 24) & 0xff;
420 _command[_index + 2] = (this.requestId >> 16) & 0xff;
430 _command[_index + 1] = (this.requestId >> 8) & 0xff;
440 _command[_index] = this.requestId & 0xff;
45 // Adjust index
460 _index = _index + 4;
47 // Write zero
480 _command[_index++] = 0;
490 _command[_index++] = 0;
500 _command[_index++] = 0;
510 _command[_index++] = 0;
52 // Write the op_code for the command
530 _command[_index + 3] = (KillCursorCommand.OP_KILL_CURSORS >> 24) & 0xff;
540 _command[_index + 2] = (KillCursorCommand.OP_KILL_CURSORS >> 16) & 0xff;
550 _command[_index + 1] = (KillCursorCommand.OP_KILL_CURSORS >> 8) & 0xff;
560 _command[_index] = KillCursorCommand.OP_KILL_CURSORS & 0xff;
57 // Adjust index
580 _index = _index + 4;
59
60 // Write zero
610 _command[_index++] = 0;
620 _command[_index++] = 0;
630 _command[_index++] = 0;
640 _command[_index++] = 0;
65
66 // Number of cursors to kill
670 var numberOfCursors = this.cursorIds.length;
680 _command[_index + 3] = (numberOfCursors >> 24) & 0xff;
690 _command[_index + 2] = (numberOfCursors >> 16) & 0xff;
700 _command[_index + 1] = (numberOfCursors >> 8) & 0xff;
710 _command[_index] = numberOfCursors & 0xff;
72 // Adjust index
730 _index = _index + 4;
74
75 // Encode all the cursors
760 for(var i = 0; i < this.cursorIds.length; i++) {
77 // Encode the cursor id
780 var low_bits = this.cursorIds[i].getLowBits();
79 // Encode low bits
800 _command[_index + 3] = (low_bits >> 24) & 0xff;
810 _command[_index + 2] = (low_bits >> 16) & 0xff;
820 _command[_index + 1] = (low_bits >> 8) & 0xff;
830 _command[_index] = low_bits & 0xff;
84 // Adjust index
850 _index = _index + 4;
86
870 var high_bits = this.cursorIds[i].getHighBits();
88 // Encode high bits
890 _command[_index + 3] = (high_bits >> 24) & 0xff;
900 _command[_index + 2] = (high_bits >> 16) & 0xff;
910 _command[_index + 1] = (high_bits >> 8) & 0xff;
920 _command[_index] = high_bits & 0xff;
93 // Adjust index
940 _index = _index + 4;
95 }
96
970 return _command;
98};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/commands/query_command.js

9%
147
14
133
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits;
3
4/**
5 Insert Document Command
6**/
71var QueryCommand = exports.QueryCommand = function(db, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) {
80 BaseCommand.call(this);
9
10 // Validate correctness off the selector
110 var object = query,
12 object_size;
130 if(Buffer.isBuffer(object)) {
140 object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
150 if(object_size != object.length) {
160 var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
170 error.name = 'MongoError';
180 throw error;
19 }
20 }
21
220 object = returnFieldSelector;
230 if(Buffer.isBuffer(object)) {
240 object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
250 if(object_size != object.length) {
260 var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
270 error.name = 'MongoError';
280 throw error;
29 }
30 }
31
32 // Make sure we don't get a null exception
330 options = options == null ? {} : options;
34 // Set up options
350 this.collectionName = collectionName;
360 this.queryOptions = queryOptions;
370 this.numberToSkip = numberToSkip;
380 this.numberToReturn = numberToReturn;
39
40 // Ensure we have no null query
410 query = query == null ? {} : query;
42 // Wrap query in the $query parameter so we can add read preferences for mongos
430 this.query = query;
440 this.returnFieldSelector = returnFieldSelector;
450 this.db = db;
46
47 // Force the slave ok flag to be set if we are not using primary read preference
480 if(this.db && this.db.slaveOk) {
490 this.queryOptions |= QueryCommand.OPTS_SLAVE;
50 }
51
52 // If checkKeys set
530 this.checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : false;
54
55 // Let us defined on a command basis if we want functions to be serialized or not
560 if(options['serializeFunctions'] != null && options['serializeFunctions']) {
570 this.serializeFunctions = true;
58 }
59};
60
611inherits(QueryCommand, BaseCommand);
62
631QueryCommand.OP_QUERY = 2004;
64
65/*
66 * Adds the read prefrence to the current command
67 */
681QueryCommand.prototype.setMongosReadPreference = function(readPreference, tags) {
69 // If we have readPreference set to true set to secondary prefered
700 if(readPreference == true) {
710 readPreference = 'secondaryPreferred';
720 } else if(readPreference == 'false') {
730 readPreference = 'primary';
74 }
75
76 // Force the slave ok flag to be set if we are not using primary read preference
770 if(readPreference != false && readPreference != 'primary') {
780 this.queryOptions |= QueryCommand.OPTS_SLAVE;
79 }
80
81 // Backward compatibility, ensure $query only set on read preference so 1.8.X works
820 if((readPreference != null || tags != null) && this.query['$query'] == null) {
830 this.query = {'$query': this.query};
84 }
85
86 // If we have no readPreference set and no tags, check if the slaveOk bit is set
870 if(readPreference == null && tags == null) {
88 // If we have a slaveOk bit set the read preference for MongoS
890 if(this.queryOptions & QueryCommand.OPTS_SLAVE) {
900 this.query['$readPreference'] = {mode: 'secondary'}
91 } else {
920 this.query['$readPreference'] = {mode: 'primary'}
93 }
94 }
95
96 // Build read preference object
970 if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') {
980 this.query['$readPreference'] = readPreference.toObject();
990 } else if(readPreference != null) {
100 // Add the read preference
1010 this.query['$readPreference'] = {mode: readPreference};
102
103 // If we have tags let's add them
1040 if(tags != null) {
1050 this.query['$readPreference']['tags'] = tags;
106 }
107 }
108}
109
110/*
111struct {
112 MsgHeader header; // standard message header
113 int32 opts; // query options. See below for details.
114 cstring fullCollectionName; // "dbname.collectionname"
115 int32 numberToSkip; // number of documents to skip when returning results
116 int32 numberToReturn; // number of documents to return in the first OP_REPLY
117 BSON query ; // query object. See below for details.
118 [ BSON returnFieldSelector; ] // OPTIONAL : selector indicating the fields to return. See below for details.
119}
120*/
1211QueryCommand.prototype.toBinary = function(bsonSettings) {
122 // Validate that we are not passing 0x00 in the colletion name
1230 if(!!~this.collectionName.indexOf("\x00")) {
1240 throw new Error("namespace cannot contain a null character");
125 }
126
127 // Total length of the command
1280 var totalLengthOfCommand = 0;
129 // Calculate total length of the document
1300 if(Buffer.isBuffer(this.query)) {
1310 totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.query.length + (4 * 4);
132 } else {
1330 totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.db.bson.calculateObjectSize(this.query, this.serializeFunctions, true) + (4 * 4);
134 }
135
136 // Calculate extra fields size
1370 if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) {
1380 if(Object.keys(this.returnFieldSelector).length > 0) {
1390 totalLengthOfCommand += this.db.bson.calculateObjectSize(this.returnFieldSelector, this.serializeFunctions, true);
140 }
1410 } else if(Buffer.isBuffer(this.returnFieldSelector)) {
1420 totalLengthOfCommand += this.returnFieldSelector.length;
143 }
144
145 // Enforce maximum bson size
1460 if(!bsonSettings.disableDriverBSONSizeCheck
147 && totalLengthOfCommand > bsonSettings.maxBsonSize)
1480 throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
149
1500 if(bsonSettings.disableDriverBSONSizeCheck
151 && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
1520 throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
153
154 // Let's build the single pass buffer command
1550 var _index = 0;
1560 var _command = new Buffer(totalLengthOfCommand);
157 // Write the header information to the buffer
1580 _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
1590 _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
1600 _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
1610 _command[_index] = totalLengthOfCommand & 0xff;
162 // Adjust index
1630 _index = _index + 4;
164 // Write the request ID
1650 _command[_index + 3] = (this.requestId >> 24) & 0xff;
1660 _command[_index + 2] = (this.requestId >> 16) & 0xff;
1670 _command[_index + 1] = (this.requestId >> 8) & 0xff;
1680 _command[_index] = this.requestId & 0xff;
169 // Adjust index
1700 _index = _index + 4;
171 // Write zero
1720 _command[_index++] = 0;
1730 _command[_index++] = 0;
1740 _command[_index++] = 0;
1750 _command[_index++] = 0;
176 // Write the op_code for the command
1770 _command[_index + 3] = (QueryCommand.OP_QUERY >> 24) & 0xff;
1780 _command[_index + 2] = (QueryCommand.OP_QUERY >> 16) & 0xff;
1790 _command[_index + 1] = (QueryCommand.OP_QUERY >> 8) & 0xff;
1800 _command[_index] = QueryCommand.OP_QUERY & 0xff;
181 // Adjust index
1820 _index = _index + 4;
183
184 // Write the query options
1850 _command[_index + 3] = (this.queryOptions >> 24) & 0xff;
1860 _command[_index + 2] = (this.queryOptions >> 16) & 0xff;
1870 _command[_index + 1] = (this.queryOptions >> 8) & 0xff;
1880 _command[_index] = this.queryOptions & 0xff;
189 // Adjust index
1900 _index = _index + 4;
191
192 // Write the collection name to the command
1930 _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
1940 _command[_index - 1] = 0;
195
196 // Write the number of documents to skip
1970 _command[_index + 3] = (this.numberToSkip >> 24) & 0xff;
1980 _command[_index + 2] = (this.numberToSkip >> 16) & 0xff;
1990 _command[_index + 1] = (this.numberToSkip >> 8) & 0xff;
2000 _command[_index] = this.numberToSkip & 0xff;
201 // Adjust index
2020 _index = _index + 4;
203
204 // Write the number of documents to return
2050 _command[_index + 3] = (this.numberToReturn >> 24) & 0xff;
2060 _command[_index + 2] = (this.numberToReturn >> 16) & 0xff;
2070 _command[_index + 1] = (this.numberToReturn >> 8) & 0xff;
2080 _command[_index] = this.numberToReturn & 0xff;
209 // Adjust index
2100 _index = _index + 4;
211
212 // Document binary length
2130 var documentLength = 0
2140 var object = this.query;
215
216 // Serialize the selector
2170 if(Buffer.isBuffer(object)) {
2180 documentLength = object.length;
219 // Copy the data into the current buffer
2200 object.copy(_command, _index);
221 } else {
222 // Serialize the document straight to the buffer
2230 documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1;
224 }
225
226 // Write the length to the document
2270 _command[_index + 3] = (documentLength >> 24) & 0xff;
2280 _command[_index + 2] = (documentLength >> 16) & 0xff;
2290 _command[_index + 1] = (documentLength >> 8) & 0xff;
2300 _command[_index] = documentLength & 0xff;
231 // Update index in buffer
2320 _index = _index + documentLength;
233 // Add terminating 0 for the object
2340 _command[_index - 1] = 0;
235
236 // Push field selector if available
2370 if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) {
2380 if(Object.keys(this.returnFieldSelector).length > 0) {
2390 var documentLength = this.db.bson.serializeWithBufferAndIndex(this.returnFieldSelector, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1;
240 // Write the length to the document
2410 _command[_index + 3] = (documentLength >> 24) & 0xff;
2420 _command[_index + 2] = (documentLength >> 16) & 0xff;
2430 _command[_index + 1] = (documentLength >> 8) & 0xff;
2440 _command[_index] = documentLength & 0xff;
245 // Update index in buffer
2460 _index = _index + documentLength;
247 // Add terminating 0 for the object
2480 _command[_index - 1] = 0;
249 }
2500 } if(this.returnFieldSelector != null && Buffer.isBuffer(this.returnFieldSelector)) {
251 // Document binary length
2520 var documentLength = 0
2530 var object = this.returnFieldSelector;
254
255 // Serialize the selector
2560 documentLength = object.length;
257 // Copy the data into the current buffer
2580 object.copy(_command, _index);
259
260 // Write the length to the document
2610 _command[_index + 3] = (documentLength >> 24) & 0xff;
2620 _command[_index + 2] = (documentLength >> 16) & 0xff;
2630 _command[_index + 1] = (documentLength >> 8) & 0xff;
2640 _command[_index] = documentLength & 0xff;
265 // Update index in buffer
2660 _index = _index + documentLength;
267 // Add terminating 0 for the object
2680 _command[_index - 1] = 0;
269 }
270
271 // Return finished command
2720 return _command;
273};
274
275// Constants
2761QueryCommand.OPTS_NONE = 0;
2771QueryCommand.OPTS_TAILABLE_CURSOR = 2;
2781QueryCommand.OPTS_SLAVE = 4;
2791QueryCommand.OPTS_OPLOG_REPLAY = 8;
2801QueryCommand.OPTS_NO_CURSOR_TIMEOUT = 16;
2811QueryCommand.OPTS_AWAIT_DATA = 32;
2821QueryCommand.OPTS_EXHAUST = 64;
2831QueryCommand.OPTS_PARTIAL = 128;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/commands/update_command.js

6%
103
7
96
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits;
3
4/**
5 Update Document Command
6**/
71var UpdateCommand = exports.UpdateCommand = function(db, collectionName, spec, document, options) {
80 BaseCommand.call(this);
9
100 var object = spec;
110 if(Buffer.isBuffer(object)) {
120 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
130 if(object_size != object.length) {
140 var error = new Error("update spec raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
150 error.name = 'MongoError';
160 throw error;
17 }
18 }
19
200 var object = document;
210 if(Buffer.isBuffer(object)) {
220 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
230 if(object_size != object.length) {
240 var error = new Error("update document raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
250 error.name = 'MongoError';
260 throw error;
27 }
28 }
29
300 this.collectionName = collectionName;
310 this.spec = spec;
320 this.document = document;
330 this.db = db;
340 this.serializeFunctions = false;
350 this.checkKeys = typeof options.checkKeys != 'boolean' ? false : options.checkKeys;
36
37 // Generate correct flags
380 var db_upsert = 0;
390 var db_multi_update = 0;
400 db_upsert = options != null && options['upsert'] != null ? (options['upsert'] == true ? 1 : 0) : db_upsert;
410 db_multi_update = options != null && options['multi'] != null ? (options['multi'] == true ? 1 : 0) : db_multi_update;
42
43 // Flags
440 this.flags = parseInt(db_multi_update.toString() + db_upsert.toString(), 2);
45 // Let us defined on a command basis if we want functions to be serialized or not
460 if(options['serializeFunctions'] != null && options['serializeFunctions']) {
470 this.serializeFunctions = true;
48 }
49};
50
511inherits(UpdateCommand, BaseCommand);
52
531UpdateCommand.OP_UPDATE = 2001;
54
55/*
56struct {
57 MsgHeader header; // standard message header
58 int32 ZERO; // 0 - reserved for future use
59 cstring fullCollectionName; // "dbname.collectionname"
60 int32 flags; // bit vector. see below
61 BSON spec; // the query to select the document
62 BSON document; // the document data to update with or insert
63}
64*/
651UpdateCommand.prototype.toBinary = function(bsonSettings) {
66 // Validate that we are not passing 0x00 in the colletion name
670 if(!!~this.collectionName.indexOf("\x00")) {
680 throw new Error("namespace cannot contain a null character");
69 }
70
71 // Calculate total length of the document
720 var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.spec, false, true) +
73 this.db.bson.calculateObjectSize(this.document, this.serializeFunctions, true) + (4 * 4);
74
75 // Enforce maximum bson size
760 if(!bsonSettings.disableDriverBSONSizeCheck
77 && totalLengthOfCommand > bsonSettings.maxBsonSize)
780 throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
79
800 if(bsonSettings.disableDriverBSONSizeCheck
81 && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
820 throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
83
84 // Let's build the single pass buffer command
850 var _index = 0;
860 var _command = new Buffer(totalLengthOfCommand);
87 // Write the header information to the buffer
880 _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
890 _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
900 _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
910 _command[_index] = totalLengthOfCommand & 0xff;
92 // Adjust index
930 _index = _index + 4;
94 // Write the request ID
950 _command[_index + 3] = (this.requestId >> 24) & 0xff;
960 _command[_index + 2] = (this.requestId >> 16) & 0xff;
970 _command[_index + 1] = (this.requestId >> 8) & 0xff;
980 _command[_index] = this.requestId & 0xff;
99 // Adjust index
1000 _index = _index + 4;
101 // Write zero
1020 _command[_index++] = 0;
1030 _command[_index++] = 0;
1040 _command[_index++] = 0;
1050 _command[_index++] = 0;
106 // Write the op_code for the command
1070 _command[_index + 3] = (UpdateCommand.OP_UPDATE >> 24) & 0xff;
1080 _command[_index + 2] = (UpdateCommand.OP_UPDATE >> 16) & 0xff;
1090 _command[_index + 1] = (UpdateCommand.OP_UPDATE >> 8) & 0xff;
1100 _command[_index] = UpdateCommand.OP_UPDATE & 0xff;
111 // Adjust index
1120 _index = _index + 4;
113
114 // Write zero
1150 _command[_index++] = 0;
1160 _command[_index++] = 0;
1170 _command[_index++] = 0;
1180 _command[_index++] = 0;
119
120 // Write the collection name to the command
1210 _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
1220 _command[_index - 1] = 0;
123
124 // Write the update flags
1250 _command[_index + 3] = (this.flags >> 24) & 0xff;
1260 _command[_index + 2] = (this.flags >> 16) & 0xff;
1270 _command[_index + 1] = (this.flags >> 8) & 0xff;
1280 _command[_index] = this.flags & 0xff;
129 // Adjust index
1300 _index = _index + 4;
131
132 // Document binary length
1330 var documentLength = 0
1340 var object = this.spec;
135
136 // Serialize the selector
137 // If we are passing a raw buffer, do minimal validation
1380 if(Buffer.isBuffer(object)) {
1390 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
1400 if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
1410 documentLength = object.length;
142 // Copy the data into the current buffer
1430 object.copy(_command, _index);
144 } else {
1450 documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, false) - _index + 1;
146 }
147
148 // Write the length to the document
1490 _command[_index + 3] = (documentLength >> 24) & 0xff;
1500 _command[_index + 2] = (documentLength >> 16) & 0xff;
1510 _command[_index + 1] = (documentLength >> 8) & 0xff;
1520 _command[_index] = documentLength & 0xff;
153 // Update index in buffer
1540 _index = _index + documentLength;
155 // Add terminating 0 for the object
1560 _command[_index - 1] = 0;
157
158 // Document binary length
1590 var documentLength = 0
1600 var object = this.document;
161
162 // Serialize the document
163 // If we are passing a raw buffer, do minimal validation
1640 if(Buffer.isBuffer(object)) {
1650 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
1660 if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
1670 documentLength = object.length;
168 // Copy the data into the current buffer
1690 object.copy(_command, _index);
170 } else {
1710 documentLength = this.db.bson.serializeWithBufferAndIndex(object, false, _command, _index, this.serializeFunctions) - _index + 1;
172 }
173
174 // Write the length to the document
1750 _command[_index + 3] = (documentLength >> 24) & 0xff;
1760 _command[_index + 2] = (documentLength >> 16) & 0xff;
1770 _command[_index + 1] = (documentLength >> 8) & 0xff;
1780 _command[_index] = documentLength & 0xff;
179 // Update index in buffer
1800 _index = _index + documentLength;
181 // Add terminating 0 for the object
1820 _command[_index - 1] = 0;
183
1840 return _command;
185};
186
187// Constants
1881UpdateCommand.DB_UPSERT = 0;
1891UpdateCommand.DB_MULTI_UPDATE = 1;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/base.js

12%
196
24
172
LineHitsSource
11var EventEmitter = require('events').EventEmitter
2 , inherits = require('util').inherits
3 , utils = require('../utils')
4 , mongodb_cr_authenticate = require('../auth/mongodb_cr.js').authenticate
5 , mongodb_gssapi_authenticate = require('../auth/mongodb_gssapi.js').authenticate
6 , mongodb_sspi_authenticate = require('../auth/mongodb_sspi.js').authenticate
7 , mongodb_plain_authenticate = require('../auth/mongodb_plain.js').authenticate
8 , mongodb_x509_authenticate = require('../auth/mongodb_x509.js').authenticate;
9
101var id = 0;
11
12/**
13 * Internal class for callback storage
14 * @ignore
15 */
161var CallbackStore = function() {
17 // Make class an event emitter
180 EventEmitter.call(this);
19 // Add a info about call variable
200 this._notReplied = {};
210 this.id = id++;
22}
23
24/**
25 * @ignore
26 */
271inherits(CallbackStore, EventEmitter);
28
291CallbackStore.prototype.notRepliedToIds = function() {
300 return Object.keys(this._notReplied);
31}
32
331CallbackStore.prototype.callbackInfo = function(id) {
340 return this._notReplied[id];
35}
36
37/**
38 * Internal class for holding non-executed commands
39 * @ignore
40 */
411var NonExecutedOperationStore = function(config) {
420 var commands = {
43 read: []
44 , write_reads: []
45 , write: []
46 };
47
48 // Execute all callbacks
490 var fireCallbacksWithError = function(error, commands) {
500 while(commands.length > 0) {
510 var command = commands.shift();
520 if(typeof command.callback == 'function') {
530 command.callback(error);
54 }
55 }
56 }
57
580 this.count = function() {
590 return commands.read.length
60 + commands.write_reads.length
61 + commands.write.length;
62 }
63
640 this.write = function(op) {
650 commands.write.push(op);
66 }
67
680 this.read_from_writer = function(op) {
690 commands.write_reads.push(op);
70 }
71
720 this.read = function(op) {
730 commands.read.push(op);
74 }
75
760 this.validateBufferLimit = function(numberToFailOn) {
770 if(numberToFailOn == -1 || numberToFailOn == null)
780 return true;
79
80 // Error passed back
810 var error = utils.toError("No connection operations buffering limit of " + numberToFailOn + " reached");
82
83 // If we have passed the number of items to buffer we need to fail
840 if(numberToFailOn < this.count()) {
85 // Fail all of the callbacks
860 fireCallbacksWithError(error, commands.read);
870 fireCallbacksWithError(error, commands.write_reads);
880 fireCallbacksWithError(error, commands.write);
89 }
90
91 // Return false
920 return false;
93 }
94
950 this.execute_queries = function(executeInsertCommand) {
960 var connection = config.checkoutReader();
970 if(connection == null || connection instanceof Error) return;
98
99 // Write out all the queries
1000 while(commands.read.length > 0) {
101 // Get the next command
1020 var command = commands.read.shift();
1030 command.options.connection = connection;
104 // Execute the next command
1050 command.executeQueryCommand(command.db, command.db_command, command.options, command.callback);
106 }
107 }
108
1090 this.execute_writes = function() {
1100 var connection = config.checkoutWriter();
1110 if(connection == null || connection instanceof Error) return;
112
113 // Write out all the queries to the primary
1140 while(commands.write_reads.length > 0) {
115 // Get the next command
1160 var command = commands.write_reads.shift();
1170 command.options.connection = connection;
118 // Execute the next command
1190 command.executeQueryCommand(command.db, command.db_command, command.options, command.callback);
120 }
121
122 // Execute all write operations
1230 while(commands.write.length > 0) {
124 // Get the next command
1250 var command = commands.write.shift();
126 // Set the connection
1270 command.options.connection = connection;
128 // Execute the next command
1290 command.executeInsertCommand(command.db, command.db_command, command.options, command.callback);
130 }
131 }
132}
133
134/**
135 * Internal class for authentication storage
136 * @ignore
137 */
1381var AuthStore = function() {
1390 var _auths = [];
140
1410 this.add = function(authMechanism, dbName, username, password, authdbName, gssapiServiceName) {
142 // Check for duplicates
1430 if(!this.contains(dbName)) {
144 // Base config
1450 var config = {
146 'username':username
147 , 'password':password
148 , 'db': dbName
149 , 'authMechanism': authMechanism
150 , 'gssapiServiceName': gssapiServiceName
151 };
152
153 // Add auth source if passed in
1540 if(typeof authdbName == 'string') {
1550 config['authdb'] = authdbName;
156 }
157
158 // Push the config
1590 _auths.push(config);
160 }
161 }
162
1630 this.contains = function(dbName) {
1640 for(var i = 0; i < _auths.length; i++) {
1650 if(_auths[i].db == dbName) return true;
166 }
167
1680 return false;
169 }
170
1710 this.remove = function(dbName) {
1720 var newAuths = [];
173
174 // Filter out all the login details
1750 for(var i = 0; i < _auths.length; i++) {
1760 if(_auths[i].db != dbName) newAuths.push(_auths[i]);
177 }
178
179 // Set the filtered list
1800 _auths = newAuths;
181 }
182
1830 this.get = function(index) {
1840 return _auths[index];
185 }
186
1870 this.length = function() {
1880 return _auths.length;
189 }
190
1910 this.toArray = function() {
1920 return _auths.slice(0);
193 }
194}
195
196/**
197 * Internal class for storing db references
198 * @ignore
199 */
2001var DbStore = function() {
2010 var _dbs = [];
202
2030 this.add = function(db) {
2040 var found = false;
205
206 // Only add if it does not exist already
2070 for(var i = 0; i < _dbs.length; i++) {
2080 if(db.databaseName == _dbs[i].databaseName) found = true;
209 }
210
211 // Only add if it does not already exist
2120 if(!found) {
2130 _dbs.push(db);
214 }
215 }
216
2170 this.reset = function() {
2180 _dbs = [];
219 }
220
2210 this.db = function() {
2220 return _dbs;
223 }
224
2250 this.fetch = function(databaseName) {
226 // Only add if it does not exist already
2270 for(var i = 0; i < _dbs.length; i++) {
2280 if(databaseName == _dbs[i].databaseName)
2290 return _dbs[i];
230 }
231
2320 return null;
233 }
234
2350 this.emit = function(event, message, object, reset, filterDb, rethrow_if_no_listeners) {
2360 var emitted = false;
237
238 // Not emitted and we have enabled rethrow, let process.uncaughtException
239 // deal with the issue
2400 if(!emitted && rethrow_if_no_listeners) {
2410 return process.nextTick(function() {
2420 throw message;
243 })
244 }
245
246 // Emit the events
2470 for(var i = 0; i < _dbs.length; i++) {
2480 if(_dbs[i].listeners(event).length > 0) {
2490 if(filterDb == null || filterDb.databaseName !== _dbs[i].databaseName
250 || filterDb.tag !== _dbs[i].tag) {
2510 _dbs[i].emit(event, message, object == null ? _dbs[i] : object);
2520 emitted = true;
253 }
254 }
255 }
256
257 // Emit error message
2580 if(message
259 && event == 'error'
260 && !emitted
261 && rethrow_if_no_listeners
262 && object && object.db) {
2630 process.nextTick(function() {
2640 object.db.emit(event, message, null);
265 })
266 }
267 }
268}
269
2701var Base = function Base() {
2710 EventEmitter.call(this);
272
273 // Callback store is part of connection specification
2740 if(Base._callBackStore == null) {
2750 Base._callBackStore = new CallbackStore();
276 }
277
278 // Create a new callback store
2790 this._callBackStore = new CallbackStore();
280 // All commands not being executed
2810 this._commandsStore = new NonExecutedOperationStore(this);
282 // Create a new auth store
2830 this.auth = new AuthStore();
284 // Contains all the dbs attached to this server config
2850 this._dbStore = new DbStore();
286}
287
288/**
289 * @ignore
290 */
2911inherits(Base, EventEmitter);
292
293/**
294 * @ignore
295 */
2961Base.prototype._apply_auths = function(db, callback) {
2970 _apply_auths_serially(this, db, this.auth.toArray(), callback);
298}
299
3001var _apply_auths_serially = function(self, db, auths, callback) {
3010 if(auths.length == 0) return callback(null, null);
302 // Get the first auth
3030 var auth = auths.shift();
3040 var connections = self.allRawConnections();
3050 var connectionsLeft = connections.length;
3060 var options = {};
307
3080 if(auth.authMechanism == 'GSSAPI') {
309 // We have the kerberos library, execute auth process
3100 if(process.platform == 'win32') {
3110 mongodb_sspi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
312 } else {
3130 mongodb_gssapi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
314 }
3150 } else if(auth.authMechanism == 'MONGODB-CR') {
3160 mongodb_cr_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
3170 } else if(auth.authMechanism == 'PLAIN') {
3180 mongodb_plain_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
3190 } else if(auth.authMechanism == 'MONGODB-X509') {
3200 mongodb_x509_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
321 }
322}
323
324/**
325 * Fire all the errors
326 * @ignore
327 */
3281Base.prototype.__executeAllCallbacksWithError = function(err) {
329 // Check all callbacks
3300 var keys = Object.keys(this._callBackStore._notReplied);
331 // For each key check if it's a callback that needs to be returned
3320 for(var j = 0; j < keys.length; j++) {
3330 var info = this._callBackStore._notReplied[keys[j]];
334 // Execute callback with error
3350 this._callBackStore.emit(keys[j], err, null);
336 // Remove the key
3370 delete this._callBackStore._notReplied[keys[j]];
338 // Force cleanup _events, node.js seems to set it as a null value
3390 if(this._callBackStore._events) {
3400 delete this._callBackStore._events[keys[j]];
341 }
342 }
343}
344
345/**
346 * Fire all the errors
347 * @ignore
348 */
3491Base.prototype.__executeAllServerSpecificErrorCallbacks = function(host, port, err) {
350 // Check all callbacks
3510 var keys = Object.keys(this._callBackStore._notReplied);
352 // For each key check if it's a callback that needs to be returned
3530 for(var j = 0; j < keys.length; j++) {
3540 var info = this._callBackStore._notReplied[keys[j]];
355
3560 if(info.connection) {
357 // Unpack the connection settings
3580 var _host = info.connection.socketOptions.host;
3590 var _port = info.connection.socketOptions.port;
360 // If the server matches execute the callback with the error
3610 if(_port == port && _host == host) {
3620 this._callBackStore.emit(keys[j], err, null);
363 // Remove the key
3640 delete this._callBackStore._notReplied[keys[j]];
365 // Force cleanup _events, node.js seems to set it as a null value
3660 if(this._callBackStore._events) {
3670 delete this._callBackStore._events[keys[j]];
368 }
369 }
370 }
371 }
372}
373
374/**
375 * Register a handler
376 * @ignore
377 * @api private
378 */
3791Base.prototype._registerHandler = function(db_command, raw, connection, exhaust, callback) {
380 // Check if we have exhausted
3810 if(typeof exhaust == 'function') {
3820 callback = exhaust;
3830 exhaust = false;
384 }
385
386 // Add the callback to the list of handlers
3870 this._callBackStore.once(db_command.getRequestId(), callback);
388 // Add the information about the reply
3890 this._callBackStore._notReplied[db_command.getRequestId().toString()] = {start: new Date().getTime(), 'raw': raw, connection:connection, exhaust:exhaust};
390}
391
392/**
393 * Re-Register a handler, on the cursor id f.ex
394 * @ignore
395 * @api private
396 */
3971Base.prototype._reRegisterHandler = function(newId, object, callback) {
398 // Add the callback to the list of handlers
3990 this._callBackStore.once(newId, object.callback.listener);
400 // Add the information about the reply
4010 this._callBackStore._notReplied[newId] = object.info;
402}
403
404/**
405 *
406 * @ignore
407 * @api private
408 */
4091Base.prototype._flushAllCallHandlers = function(err) {
4100 var keys = Object.keys(this._callBackStore._notReplied);
411
4120 for(var i = 0; i < keys.length; i++) {
4130 this._callHandler(keys[i], null, err);
414 }
415}
416
417/**
418 *
419 * @ignore
420 * @api private
421 */
4221Base.prototype._callHandler = function(id, document, err) {
4230 var self = this;
424
425 // If there is a callback peform it
4260 if(this._callBackStore.listeners(id).length >= 1) {
427 // Get info object
4280 var info = this._callBackStore._notReplied[id];
429 // Delete the current object
4300 delete this._callBackStore._notReplied[id];
431 // Call the handle directly don't emit
4320 var callback = this._callBackStore.listeners(id)[0].listener;
433 // Remove the listeners
4340 this._callBackStore.removeAllListeners(id);
435 // Force key deletion because it nulling it not deleting in 0.10.X
4360 if(this._callBackStore._events) {
4370 delete this._callBackStore._events[id];
438 }
439
4400 try {
441 // Execute the callback if one was provided
4420 if(typeof callback == 'function') callback(err, document, info.connection);
443 } catch(err) {
4440 self._emitAcrossAllDbInstances(self, null, "error", utils.toError(err), self, true, true);
445 }
446 }
447}
448
449/**
450 *
451 * @ignore
452 * @api private
453 */
4541Base.prototype._hasHandler = function(id) {
4550 return this._callBackStore.listeners(id).length >= 1;
456}
457
458/**
459 *
460 * @ignore
461 * @api private
462 */
4631Base.prototype._removeHandler = function(id) {
464 // Remove the information
4650 if(this._callBackStore._notReplied[id] != null) delete this._callBackStore._notReplied[id];
466 // Remove the callback if it's registered
4670 this._callBackStore.removeAllListeners(id);
468 // Force cleanup _events, node.js seems to set it as a null value
4690 if(this._callBackStore._events) {
4700 delete this._callBackStore._events[id];
471 }
472}
473
474/**
475 *
476 * @ignore
477 * @api private
478 */
4791Base.prototype._findHandler = function(id) {
4800 var info = this._callBackStore._notReplied[id];
481 // Return the callback
4820 return {info:info, callback:(this._callBackStore.listeners(id).length >= 1) ? this._callBackStore.listeners(id)[0] : null}
483}
484
485/**
486 *
487 * @ignore
488 * @api private
489 */
4901Base.prototype._emitAcrossAllDbInstances = function(server, filterDb, event, message, object, resetConnection, rethrow_if_no_listeners) {
4910 if(resetConnection) {
4920 var dbs = this._dbStore.db();
493
4940 for(var i = 0; i < dbs.length; i++) {
4950 if(typeof dbs[i].openCalled != 'undefined')
4960 dbs[i].openCalled = false;
497 }
498 }
499
500 // Fire event
5010 this._dbStore.emit(event, message, object, resetConnection, filterDb, rethrow_if_no_listeners);
502}
503
5041exports.Base = Base;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/connection.js

8%
233
19
214
LineHitsSource
11var utils = require('./connection_utils'),
2 inherits = require('util').inherits,
3 net = require('net'),
4 EventEmitter = require('events').EventEmitter,
5 inherits = require('util').inherits,
6 binaryutils = require('../utils'),
7 tls = require('tls');
8
91var Connection = exports.Connection = function(id, socketOptions) {
100 var self = this;
11 // Set up event emitter
120 EventEmitter.call(this);
13 // Store all socket options
140 this.socketOptions = socketOptions ? socketOptions : {host:'localhost', port:27017, domainSocket:false};
15 // Set keep alive default if not overriden
160 if(this.socketOptions.keepAlive == null && (process.platform !== "sunos" || process.platform !== "win32")) this.socketOptions.keepAlive = 100;
17 // Id for the connection
180 this.id = id;
19 // State of the connection
200 this.connected = false;
21 // Set if this is a domain socket
220 this.domainSocket = this.socketOptions.domainSocket;
23
24 // Supported min and max wire protocol
250 this.minWireVersion = 0;
260 this.maxWireVersion = 2;
27
28 //
29 // Connection parsing state
30 //
310 this.maxBsonSize = socketOptions.maxBsonSize ? socketOptions.maxBsonSize : Connection.DEFAULT_MAX_BSON_SIZE;
320 this.maxMessageSizeBytes = socketOptions.maxMessageSizeBytes ? socketOptions.maxMessageSizeBytes : Connection.DEFAULT_MAX_MESSAGE_SIZE;
33 // Contains the current message bytes
340 this.buffer = null;
35 // Contains the current message size
360 this.sizeOfMessage = 0;
37 // Contains the readIndex for the messaage
380 this.bytesRead = 0;
39 // Contains spill over bytes from additional messages
400 this.stubBuffer = 0;
41
42 // Just keeps list of events we allow
430 this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[], end:[]};
44
45 // Just keeps list of events we allow
460 resetHandlers(this, false);
47 // Bson object
480 this.maxBsonSettings = {
49 disableDriverBSONSizeCheck: this.socketOptions['disableDriverBSONSizeCheck'] || false
50 , maxBsonSize: this.maxBsonSize
51 , maxMessageSizeBytes: this.maxMessageSizeBytes
52 }
53
54 // Allow setting the socketTimeoutMS on all connections
55 // to work around issues such as secondaries blocking due to compaction
560 Object.defineProperty(this, "socketTimeoutMS", {
57 enumerable: true
580 , get: function () { return self.socketOptions.socketTimeoutMS; }
59 , set: function (value) {
60 // Set the socket timeoutMS value
610 self.socketOptions.socketTimeoutMS = value;
62 // Set the physical connection timeout
630 self.connection.setTimeout(self.socketOptions.socketTimeoutMS);
64 }
65 });
66}
67
68// Set max bson size
691Connection.DEFAULT_MAX_BSON_SIZE = 1024 * 1024 * 4;
70// Set default to max bson to avoid overflow or bad guesses
711Connection.DEFAULT_MAX_MESSAGE_SIZE = Connection.DEFAULT_MAX_BSON_SIZE;
72
73// Inherit event emitter so we can emit stuff wohoo
741inherits(Connection, EventEmitter);
75
761Connection.prototype.start = function() {
770 var self = this;
78
79 // If we have a normal connection
800 if(this.socketOptions.ssl) {
81 // Create new connection instance
820 if(this.domainSocket) {
830 this.connection = net.createConnection(this.socketOptions.host);
84 } else {
850 this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host);
86 }
870 if(this.logger != null && this.logger.doDebug){
880 this.logger.debug("opened connection", this.socketOptions);
89 }
90
91 // Set options on the socket
920 this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout);
93 // Work around for 0.4.X
940 if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay);
95 // Set keep alive if defined
960 if(process.version.indexOf("v0.4") == -1) {
970 if(this.socketOptions.keepAlive > 0) {
980 this.connection.setKeepAlive(true, this.socketOptions.keepAlive);
99 } else {
1000 this.connection.setKeepAlive(false);
101 }
102 }
103
104 // Check if the driver should validate the certificate
1050 var validate_certificates = this.socketOptions.sslValidate == true ? true : false;
106
107 // Create options for the tls connection
1080 var tls_options = {
109 socket: this.connection
110 , rejectUnauthorized: false
111 }
112
113 // If we wish to validate the certificate we have provided a ca store
1140 if(validate_certificates) {
1150 tls_options.ca = this.socketOptions.sslCA;
116 }
117
118 // If we have a certificate to present
1190 if(this.socketOptions.sslCert) {
1200 tls_options.cert = this.socketOptions.sslCert;
1210 tls_options.key = this.socketOptions.sslKey;
122 }
123
124 // If the driver has been provided a private key password
1250 if(this.socketOptions.sslPass) {
1260 tls_options.passphrase = this.socketOptions.sslPass;
127 }
128
129 // Contains the cleartext stream
1300 var cleartext = null;
131 // Attempt to establish a TLS connection to the server
1320 try {
1330 cleartext = tls.connect(this.socketOptions.port, this.socketOptions.host, tls_options, function() {
134 // If we have a ssl certificate validation error return an error
1350 if(cleartext.authorizationError && validate_certificates) {
136 // Emit an error
1370 return self.emit("error", cleartext.authorizationError, self, {ssl:true});
138 }
139
140 // Connect to the server
1410 connectHandler(self)();
142 })
143 } catch(err) {
1440 return self.emit("error", "SSL connection failed", self, {ssl:true});
145 }
146
147 // Save the output stream
1480 this.writeSteam = cleartext;
149
150 // Set up data handler for the clear stream
1510 cleartext.on("data", createDataHandler(this));
152 // Do any handling of end event of the stream
1530 cleartext.on("end", endHandler(this));
1540 cleartext.on("error", errorHandler(this));
155
156 // Handle any errors
1570 this.connection.on("error", errorHandler(this));
158 // Handle timeout
1590 this.connection.on("timeout", timeoutHandler(this));
160 // Handle drain event
1610 this.connection.on("drain", drainHandler(this));
162 // Handle the close event
1630 this.connection.on("close", closeHandler(this));
164 } else {
165 // Create new connection instance
1660 if(this.domainSocket) {
1670 this.connection = net.createConnection(this.socketOptions.host);
168 } else {
1690 this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host);
170 }
1710 if(this.logger != null && this.logger.doDebug){
1720 this.logger.debug("opened connection", this.socketOptions);
173 }
174
175 // Set options on the socket
1760 this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout);
177 // Work around for 0.4.X
1780 if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay);
179 // Set keep alive if defined
1800 if(process.version.indexOf("v0.4") == -1) {
1810 if(this.socketOptions.keepAlive > 0) {
1820 this.connection.setKeepAlive(true, this.socketOptions.keepAlive);
183 } else {
1840 this.connection.setKeepAlive(false);
185 }
186 }
187
188 // Set up write stream
1890 this.writeSteam = this.connection;
190 // Add handlers
1910 this.connection.on("error", errorHandler(this));
192 // Add all handlers to the socket to manage it
1930 this.connection.on("connect", connectHandler(this));
194 // this.connection.on("end", endHandler(this));
1950 this.connection.on("data", createDataHandler(this));
1960 this.connection.on("timeout", timeoutHandler(this));
1970 this.connection.on("drain", drainHandler(this));
1980 this.connection.on("close", closeHandler(this));
199 }
200}
201
202// Check if the sockets are live
2031Connection.prototype.isConnected = function() {
2040 return this.connected && !this.connection.destroyed && this.connection.writable && this.connection.readable;
205}
206
207// Validate if the driver supports this server
2081Connection.prototype.isCompatible = function() {
2090 if(this.serverCapabilities == null) return true;
210 // Is compatible with backward server
2110 if(this.serverCapabilities.minWireVersion == 0
2120 && this.serverCapabilities.maxWireVersion ==0) return true;
213
214 // Check if we overlap
2150 if(this.serverCapabilities.minWireVersion >= this.minWireVersion
2160 && this.serverCapabilities.maxWireVersion <= this.maxWireVersion) return true;
217
218 // Not compatible
2190 return false;
220}
221
222// Write the data out to the socket
2231Connection.prototype.write = function(command, callback) {
2240 try {
225 // If we have a list off commands to be executed on the same socket
2260 if(Array.isArray(command)) {
2270 for(var i = 0; i < command.length; i++) {
2280 try {
229 // Pass in the bson validation settings (validate early)
2300 var binaryCommand = command[i].toBinary(this.maxBsonSettings)
231
2320 if(this.logger != null && this.logger.doDebug)
2330 this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command[i]});
234
2350 this.writeSteam.write(binaryCommand);
236 } catch(err) {
2370 return callback(err, null);
238 }
239 }
240 } else {
2410 try {
242 // Pass in the bson validation settings (validate early)
2430 var binaryCommand = command.toBinary(this.maxBsonSettings)
244 // Do we have a logger active log the event
2450 if(this.logger != null && this.logger.doDebug)
2460 this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command[i]});
247 // Write the binary command out to socket
2480 this.writeSteam.write(binaryCommand);
249 } catch(err) {
2500 return callback(err, null)
251 }
252 }
253 } catch (err) {
2540 if(typeof callback === 'function') callback(err);
255 }
256}
257
258// Force the closure of the connection
2591Connection.prototype.close = function() {
260 // clear out all the listeners
2610 resetHandlers(this, true);
262 // Add a dummy error listener to catch any weird last moment errors (and ignore them)
2630 this.connection.on("error", function() {})
264 // destroy connection
2650 this.connection.destroy();
2660 if(this.logger != null && this.logger.doDebug){
2670 this.logger.debug("closed connection", this.connection);
268 }
269}
270
271// Reset all handlers
2721var resetHandlers = function(self, clearListeners) {
2730 self.eventHandlers = {error:[], connect:[], close:[], end:[], timeout:[], parseError:[], message:[]};
274
275 // If we want to clear all the listeners
2760 if(clearListeners && self.connection != null) {
2770 var keys = Object.keys(self.eventHandlers);
278 // Remove all listeners
2790 for(var i = 0; i < keys.length; i++) {
2800 self.connection.removeAllListeners(keys[i]);
281 }
282 }
283}
284
285//
286// Handlers
287//
288
289// Connect handler
2901var connectHandler = function(self) {
2910 return function(data) {
292 // Set connected
2930 self.connected = true;
294 // Now that we are connected set the socket timeout
2950 self.connection.setTimeout(self.socketOptions.socketTimeoutMS != null ? self.socketOptions.socketTimeoutMS : self.socketOptions.timeout);
296 // Emit the connect event with no error
2970 self.emit("connect", null, self);
298 }
299}
300
3011var createDataHandler = exports.Connection.createDataHandler = function(self) {
302 // We need to handle the parsing of the data
303 // and emit the messages when there is a complete one
3040 return function(data) {
305 // Parse until we are done with the data
3060 while(data.length > 0) {
307 // If we still have bytes to read on the current message
3080 if(self.bytesRead > 0 && self.sizeOfMessage > 0) {
309 // Calculate the amount of remaining bytes
3100 var remainingBytesToRead = self.sizeOfMessage - self.bytesRead;
311 // Check if the current chunk contains the rest of the message
3120 if(remainingBytesToRead > data.length) {
313 // Copy the new data into the exiting buffer (should have been allocated when we know the message size)
3140 data.copy(self.buffer, self.bytesRead);
315 // Adjust the number of bytes read so it point to the correct index in the buffer
3160 self.bytesRead = self.bytesRead + data.length;
317
318 // Reset state of buffer
3190 data = new Buffer(0);
320 } else {
321 // Copy the missing part of the data into our current buffer
3220 data.copy(self.buffer, self.bytesRead, 0, remainingBytesToRead);
323 // Slice the overflow into a new buffer that we will then re-parse
3240 data = data.slice(remainingBytesToRead);
325
326 // Emit current complete message
3270 try {
3280 var emitBuffer = self.buffer;
329 // Reset state of buffer
3300 self.buffer = null;
3310 self.sizeOfMessage = 0;
3320 self.bytesRead = 0;
3330 self.stubBuffer = null;
334 // Emit the buffer
3350 self.emit("message", emitBuffer, self);
336 } catch(err) {
3370 var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
338 sizeOfMessage:self.sizeOfMessage,
339 bytesRead:self.bytesRead,
340 stubBuffer:self.stubBuffer}};
3410 if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
342 // We got a parse Error fire it off then keep going
3430 self.emit("parseError", errorObject, self);
344 }
345 }
346 } else {
347 // Stub buffer is kept in case we don't get enough bytes to determine the
348 // size of the message (< 4 bytes)
3490 if(self.stubBuffer != null && self.stubBuffer.length > 0) {
350
351 // If we have enough bytes to determine the message size let's do it
3520 if(self.stubBuffer.length + data.length > 4) {
353 // Prepad the data
3540 var newData = new Buffer(self.stubBuffer.length + data.length);
3550 self.stubBuffer.copy(newData, 0);
3560 data.copy(newData, self.stubBuffer.length);
357 // Reassign for parsing
3580 data = newData;
359
360 // Reset state of buffer
3610 self.buffer = null;
3620 self.sizeOfMessage = 0;
3630 self.bytesRead = 0;
3640 self.stubBuffer = null;
365
366 } else {
367
368 // Add the the bytes to the stub buffer
3690 var newStubBuffer = new Buffer(self.stubBuffer.length + data.length);
370 // Copy existing stub buffer
3710 self.stubBuffer.copy(newStubBuffer, 0);
372 // Copy missing part of the data
3730 data.copy(newStubBuffer, self.stubBuffer.length);
374 // Exit parsing loop
3750 data = new Buffer(0);
376 }
377 } else {
3780 if(data.length > 4) {
379 // Retrieve the message size
3800 var sizeOfMessage = binaryutils.decodeUInt32(data, 0);
381 // If we have a negative sizeOfMessage emit error and return
3820 if(sizeOfMessage < 0 || sizeOfMessage > self.maxBsonSize) {
3830 var errorObject = {err:"socketHandler", trace:'', bin:self.buffer, parseState:{
384 sizeOfMessage: sizeOfMessage,
385 bytesRead: self.bytesRead,
386 stubBuffer: self.stubBuffer}};
3870 if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
388 // We got a parse Error fire it off then keep going
3890 self.emit("parseError", errorObject, self);
3900 return;
391 }
392
393 // Ensure that the size of message is larger than 0 and less than the max allowed
3940 if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage > data.length) {
3950 self.buffer = new Buffer(sizeOfMessage);
396 // Copy all the data into the buffer
3970 data.copy(self.buffer, 0);
398 // Update bytes read
3990 self.bytesRead = data.length;
400 // Update sizeOfMessage
4010 self.sizeOfMessage = sizeOfMessage;
402 // Ensure stub buffer is null
4030 self.stubBuffer = null;
404 // Exit parsing loop
4050 data = new Buffer(0);
406
4070 } else if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage == data.length) {
4080 try {
4090 var emitBuffer = data;
410 // Reset state of buffer
4110 self.buffer = null;
4120 self.sizeOfMessage = 0;
4130 self.bytesRead = 0;
4140 self.stubBuffer = null;
415 // Exit parsing loop
4160 data = new Buffer(0);
417 // Emit the message
4180 self.emit("message", emitBuffer, self);
419 } catch (err) {
4200 var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
421 sizeOfMessage:self.sizeOfMessage,
422 bytesRead:self.bytesRead,
423 stubBuffer:self.stubBuffer}};
4240 if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
425 // We got a parse Error fire it off then keep going
4260 self.emit("parseError", errorObject, self);
427 }
4280 } else if(sizeOfMessage <= 4 || sizeOfMessage > self.maxBsonSize) {
4290 var errorObject = {err:"socketHandler", trace:null, bin:data, parseState:{
430 sizeOfMessage:sizeOfMessage,
431 bytesRead:0,
432 buffer:null,
433 stubBuffer:null}};
4340 if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
435 // We got a parse Error fire it off then keep going
4360 self.emit("parseError", errorObject, self);
437
438 // Clear out the state of the parser
4390 self.buffer = null;
4400 self.sizeOfMessage = 0;
4410 self.bytesRead = 0;
4420 self.stubBuffer = null;
443 // Exit parsing loop
4440 data = new Buffer(0);
445
446 } else {
4470 try {
4480 var emitBuffer = data.slice(0, sizeOfMessage);
449 // Reset state of buffer
4500 self.buffer = null;
4510 self.sizeOfMessage = 0;
4520 self.bytesRead = 0;
4530 self.stubBuffer = null;
454 // Copy rest of message
4550 data = data.slice(sizeOfMessage);
456 // Emit the message
4570 self.emit("message", emitBuffer, self);
458 } catch (err) {
4590 var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
460 sizeOfMessage:sizeOfMessage,
461 bytesRead:self.bytesRead,
462 stubBuffer:self.stubBuffer}};
4630 if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
464 // We got a parse Error fire it off then keep going
4650 self.emit("parseError", errorObject, self);
466 }
467
468 }
469 } else {
470 // Create a buffer that contains the space for the non-complete message
4710 self.stubBuffer = new Buffer(data.length)
472 // Copy the data to the stub buffer
4730 data.copy(self.stubBuffer, 0);
474 // Exit parsing loop
4750 data = new Buffer(0);
476 }
477 }
478 }
479 }
480 }
481}
482
4831var endHandler = function(self) {
4840 return function() {
485 // Set connected to false
4860 self.connected = false;
487 // Emit end event
4880 self.emit("end", {err: 'connection received Fin packet from [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
489 }
490}
491
4921var timeoutHandler = function(self) {
4930 return function() {
494 // Set connected to false
4950 self.connected = false;
496 // Emit timeout event
4970 self.emit("timeout", {err: 'connection to [' + self.socketOptions.host + ':' + self.socketOptions.port + '] timed out'}, self);
498 }
499}
500
5011var drainHandler = function(self) {
5020 return function() {
503 }
504}
505
5061var errorHandler = function(self) {
5070 return function(err) {
5080 self.connection.destroy();
509 // Set connected to false
5100 self.connected = false;
511 // Emit error
5120 self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
513 }
514}
515
5161var closeHandler = function(self) {
5170 return function(hadError) {
518 // If we have an error during the connection phase
5190 if(hadError && !self.connected) {
520 // Set disconnected
5210 self.connected = false;
522 // Emit error
5230 self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
524 } else {
525 // Set disconnected
5260 self.connected = false;
527 // Emit close
5280 self.emit("close", {err: 'connection closed to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
529 }
530 }
531}
532
533// Some basic defaults
5341Connection.DEFAULT_PORT = 27017;
535
536
537
538
539
540
541
542

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js

11%
124
14
110
LineHitsSource
11var utils = require('./connection_utils'),
2 inherits = require('util').inherits,
3 net = require('net'),
4 timers = require('timers'),
5 EventEmitter = require('events').EventEmitter,
6 inherits = require('util').inherits,
7 MongoReply = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/../responses/mongo_reply").MongoReply,
8 Connection = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/./connection").Connection;
9
10// Set processor, setImmediate if 0.10 otherwise nextTick
111var processor = require('../utils').processor();
12
131var ConnectionPool = exports.ConnectionPool = function(host, port, poolSize, bson, socketOptions) {
140 if(typeof host !== 'string') {
150 throw new Error("host must be specified [" + host + "]");
16 }
17
18 // Set up event emitter
190 EventEmitter.call(this);
20
21 // Keep all options for the socket in a specific collection allowing the user to specify the
22 // Wished upon socket connection parameters
230 this.socketOptions = typeof socketOptions === 'object' ? socketOptions : {};
240 this.socketOptions.host = host;
250 this.socketOptions.port = port;
260 this.socketOptions.domainSocket = false;
270 this.bson = bson;
28 // PoolSize is always + 1 for special reserved "measurment" socket (like ping, stats etc)
290 this.poolSize = poolSize;
300 this.minPoolSize = Math.floor(this.poolSize / 2) + 1;
31
32 // Check if the host is a socket
330 if(host.match(/^\//)) {
340 this.socketOptions.domainSocket = true;
350 } else if(typeof port === 'string') {
360 try {
370 port = parseInt(port, 10);
38 } catch(err) {
390 new Error("port must be specified or valid integer[" + port + "]");
40 }
410 } else if(typeof port !== 'number') {
420 throw new Error("port must be specified [" + port + "]");
43 }
44
45 // Set default settings for the socket options
460 utils.setIntegerParameter(this.socketOptions, 'timeout', 0);
47 // Delay before writing out the data to the server
480 utils.setBooleanParameter(this.socketOptions, 'noDelay', true);
49 // Delay before writing out the data to the server
500 utils.setIntegerParameter(this.socketOptions, 'keepAlive', 0);
51 // Set the encoding of the data read, default is binary == null
520 utils.setStringParameter(this.socketOptions, 'encoding', null);
53 // Allows you to set a throttling bufferSize if you need to stop overflows
540 utils.setIntegerParameter(this.socketOptions, 'bufferSize', 0);
55
56 // Internal structures
570 this.openConnections = [];
58 // Assign connection id's
590 this.connectionId = 0;
60
61 // Current index for selection of pool connection
620 this.currentConnectionIndex = 0;
63 // The pool state
640 this._poolState = 'disconnected';
65 // timeout control
660 this._timeout = false;
67 // Time to wait between connections for the pool
680 this._timeToWait = 10;
69}
70
711inherits(ConnectionPool, EventEmitter);
72
731ConnectionPool.prototype.setMaxBsonSize = function(maxBsonSize) {
740 if(maxBsonSize == null){
750 maxBsonSize = Connection.DEFAULT_MAX_BSON_SIZE;
76 }
77
780 for(var i = 0; i < this.openConnections.length; i++) {
790 this.openConnections[i].maxBsonSize = maxBsonSize;
800 this.openConnections[i].maxBsonSettings.maxBsonSize = maxBsonSize;
81 }
82}
83
841ConnectionPool.prototype.setMaxMessageSizeBytes = function(maxMessageSizeBytes) {
850 if(maxMessageSizeBytes == null){
860 maxMessageSizeBytes = Connection.DEFAULT_MAX_MESSAGE_SIZE;
87 }
88
890 for(var i = 0; i < this.openConnections.length; i++) {
900 this.openConnections[i].maxMessageSizeBytes = maxMessageSizeBytes;
910 this.openConnections[i].maxBsonSettings.maxMessageSizeBytes = maxMessageSizeBytes;
92 }
93}
94
95// Start a function
961var _connect = function(_self) {
97 // return new function() {
98 // Create a new connection instance
990 var connection = new Connection(_self.connectionId++, _self.socketOptions);
100 // Set logger on pool
1010 connection.logger = _self.logger;
102 // Connect handler
1030 connection.on("connect", function(err, connection) {
104 // Add connection to list of open connections
1050 _self.openConnections.push(connection);
106 // If the number of open connections is equal to the poolSize signal ready pool
1070 if(_self.openConnections.length === _self.poolSize && _self._poolState !== 'disconnected') {
108 // Set connected
1090 _self._poolState = 'connected';
110 // Emit pool ready
1110 _self.emit("poolReady");
1120 } else if(_self.openConnections.length < _self.poolSize) {
113 // Wait a little bit of time to let the close event happen if the server closes the connection
114 // so we don't leave hanging connections around
1150 if(typeof _self._timeToWait == 'number') {
1160 setTimeout(function() {
117 // If we are still connecting (no close events fired in between start another connection)
1180 if(_self._poolState == 'connecting') {
1190 _connect(_self);
120 }
121 }, _self._timeToWait);
122 } else {
1230 processor(function() {
124 // If we are still connecting (no close events fired in between start another connection)
1250 if(_self._poolState == 'connecting') {
1260 _connect(_self);
127 }
128 });
129 }
130 }
131 });
132
1330 var numberOfErrors = 0
134
135 // Error handler
1360 connection.on("error", function(err, connection, error_options) {
1370 numberOfErrors++;
138 // If we are already disconnected ignore the event
1390 if(_self._poolState != 'disconnected' && _self.listeners("error").length > 0) {
1400 _self.emit("error", err, connection, error_options);
141 }
142
143 // Close the connection
1440 connection.close();
145 // Set pool as disconnected
1460 _self._poolState = 'disconnected';
147 // Stop the pool
1480 _self.stop();
149 });
150
151 // Close handler
1520 connection.on("close", function() {
153 // If we are already disconnected ignore the event
1540 if(_self._poolState !== 'disconnected' && _self.listeners("close").length > 0) {
1550 _self.emit("close");
156 }
157
158 // Set disconnected
1590 _self._poolState = 'disconnected';
160 // Stop
1610 _self.stop();
162 });
163
164 // Timeout handler
1650 connection.on("timeout", function(err, connection) {
166 // If we are already disconnected ignore the event
1670 if(_self._poolState !== 'disconnected' && _self.listeners("timeout").length > 0) {
1680 _self.emit("timeout", err);
169 }
170
171 // Close the connection
1720 connection.close();
173 // Set disconnected
1740 _self._poolState = 'disconnected';
1750 _self.stop();
176 });
177
178 // Parse error, needs a complete shutdown of the pool
1790 connection.on("parseError", function() {
180 // If we are already disconnected ignore the event
1810 if(_self._poolState !== 'disconnected' && _self.listeners("parseError").length > 0) {
1820 _self.emit("parseError", new Error("parseError occured"));
183 }
184
185 // Set disconnected
1860 _self._poolState = 'disconnected';
1870 _self.stop();
188 });
189
1900 connection.on("message", function(message) {
1910 _self.emit("message", message);
192 });
193
194 // Start connection in the next tick
1950 connection.start();
196 // }();
197}
198
199
200// Start method, will throw error if no listeners are available
201// Pass in an instance of the listener that contains the api for
202// finding callbacks for a given message etc.
2031ConnectionPool.prototype.start = function() {
2040 var markerDate = new Date().getTime();
2050 var self = this;
206
2070 if(this.listeners("poolReady").length == 0) {
2080 throw "pool must have at least one listener ready that responds to the [poolReady] event";
209 }
210
211 // Set pool state to connecting
2120 this._poolState = 'connecting';
2130 this._timeout = false;
214
2150 _connect(self);
216}
217
218// Restart a connection pool (on a close the pool might be in a wrong state)
2191ConnectionPool.prototype.restart = function() {
220 // Close all connections
2210 this.stop(false);
222 // Now restart the pool
2230 this.start();
224}
225
226// Stop the connections in the pool
2271ConnectionPool.prototype.stop = function(removeListeners) {
2280 removeListeners = removeListeners == null ? true : removeListeners;
229 // Set disconnected
2300 this._poolState = 'disconnected';
231
232 // Clear all listeners if specified
2330 if(removeListeners) {
2340 this.removeAllEventListeners();
235 }
236
237 // Close all connections
2380 for(var i = 0; i < this.openConnections.length; i++) {
2390 this.openConnections[i].close();
240 }
241
242 // Clean up
2430 this.openConnections = [];
244}
245
246// Check the status of the connection
2471ConnectionPool.prototype.isConnected = function() {
248 // return this._poolState === 'connected';
2490 return this.openConnections.length > 0 && this.openConnections[0].isConnected();
250}
251
252// Checkout a connection from the pool for usage, or grab a specific pool instance
2531ConnectionPool.prototype.checkoutConnection = function(id) {
2540 var index = (this.currentConnectionIndex++ % (this.openConnections.length));
2550 var connection = this.openConnections[index];
2560 return connection;
257}
258
2591ConnectionPool.prototype.getAllConnections = function() {
2600 return this.openConnections;
261}
262
263// Remove all non-needed event listeners
2641ConnectionPool.prototype.removeAllEventListeners = function() {
2650 this.removeAllListeners("close");
2660 this.removeAllListeners("error");
2670 this.removeAllListeners("timeout");
2680 this.removeAllListeners("connect");
2690 this.removeAllListeners("end");
2700 this.removeAllListeners("parseError");
2710 this.removeAllListeners("message");
2720 this.removeAllListeners("poolReady");
273}
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/connection_utils.js

20%
15
3
12
LineHitsSource
11exports.setIntegerParameter = function(object, field, defaultValue) {
20 if(object[field] == null) {
30 object[field] = defaultValue;
40 } else if(typeof object[field] !== "number" && object[field] !== parseInt(object[field], 10)) {
50 throw "object field [" + field + "] must be a numeric integer value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]";
6 }
7}
8
91exports.setBooleanParameter = function(object, field, defaultValue) {
100 if(object[field] == null) {
110 object[field] = defaultValue;
120 } else if(typeof object[field] !== "boolean") {
130 throw "object field [" + field + "] must be a boolean value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]";
14 }
15}
16
171exports.setStringParameter = function(object, field, defaultValue) {
180 if(object[field] == null) {
190 object[field] = defaultValue;
200 } else if(typeof object[field] !== "string") {
210 throw "object field [" + field + "] must be a string value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]";
22 }
23}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/mongos.js

9%
203
20
183
LineHitsSource
11var ReadPreference = require('./read_preference').ReadPreference
2 , Base = require('./base').Base
3 , Server = require('./server').Server
4 , format = require('util').format
5 , timers = require('timers')
6 , utils = require('../utils')
7 , inherits = require('util').inherits;
8
9// Set processor, setImmediate if 0.10 otherwise nextTick
101var processor = require('../utils').processor();
11
12/**
13 * Mongos constructor provides a connection to a mongos proxy including failover to additional servers
14 *
15 * Options
16 * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number))
17 * - **ha** {Boolean, default:true}, turn on high availability, attempts to reconnect to down proxies
18 * - **haInterval** {Number, default:2000}, time between each replicaset status check.
19 *
20 * @class Represents a Mongos connection with failover to backup proxies
21 * @param {Array} list of mongos server objects
22 * @param {Object} [options] additional options for the mongos connection
23 */
241var Mongos = function Mongos(servers, options) {
25 // Set up basic
260 if(!(this instanceof Mongos))
270 return new Mongos(servers, options);
28
29 // Set up event emitter
300 Base.call(this);
31
32 // Throw error on wrong setup
330 if(servers == null || !Array.isArray(servers) || servers.length == 0)
340 throw new Error("At least one mongos proxy must be in the array");
35
36 // Ensure we have at least an empty options object
370 this.options = options == null ? {} : options;
38 // Set default connection pool options
390 this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {};
40 // Enabled ha
410 this.haEnabled = this.options['ha'] == null ? true : this.options['ha'];
420 this._haInProgress = false;
43 // How often are we checking for new servers in the replicaset
440 this.mongosStatusCheckInterval = this.options['haInterval'] == null ? 1000 : this.options['haInterval'];
45 // Save all the server connections
460 this.servers = servers;
47 // Servers we need to attempt reconnect with
480 this.downServers = {};
49 // Servers that are up
500 this.upServers = {};
51 // Up servers by ping time
520 this.upServersByUpTime = {};
53 // Emit open setup
540 this.emitOpen = this.options.emitOpen || true;
55 // Just contains the current lowest ping time and server
560 this.lowestPingTimeServer = null;
570 this.lowestPingTime = 0;
58 // Connection timeout
590 this._connectTimeoutMS = this.socketOptions.connectTimeoutMS
60 ? this.socketOptions.connectTimeoutMS
61 : 1000;
62
63 // Add options to servers
640 for(var i = 0; i < this.servers.length; i++) {
650 var server = this.servers[i];
660 server._callBackStore = this._callBackStore;
670 server.auto_reconnect = false;
68 // Default empty socket options object
690 var socketOptions = {host: server.host, port: server.port};
70 // If a socket option object exists clone it
710 if(this.socketOptions != null) {
720 var keys = Object.keys(this.socketOptions);
730 for(var k = 0; k < keys.length;k++) socketOptions[keys[i]] = this.socketOptions[keys[i]];
74 }
75
76 // Set socket options
770 server.socketOptions = socketOptions;
78 }
79
80 // Allow setting the socketTimeoutMS on all connections
81 // to work around issues such as secondaries blocking due to compaction
820 utils.setSocketTimeoutProperty(this, this.socketOptions);
83}
84
85/**
86 * @ignore
87 */
881inherits(Mongos, Base);
89
90/**
91 * @ignore
92 */
931Mongos.prototype.isMongos = function() {
940 return true;
95}
96
97/**
98 * @ignore
99 */
1001Mongos.prototype.connect = function(db, options, callback) {
1010 if('function' === typeof options) callback = options, options = {};
1020 if(options == null) options = {};
1030 if(!('function' === typeof callback)) callback = null;
1040 var self = this;
105
106 // Keep reference to parent
1070 this.db = db;
108 // Set server state to connecting
1090 this._serverState = 'connecting';
110 // Number of total servers that need to initialized (known servers)
1110 this._numberOfServersLeftToInitialize = this.servers.length;
112 // Connect handler
1130 var connectHandler = function(_server) {
1140 return function(err, result) {
1150 self._numberOfServersLeftToInitialize = self._numberOfServersLeftToInitialize - 1;
116
117 // Add the server to the list of servers that are up
1180 if(!err) {
1190 self.upServers[format("%s:%s", _server.host, _server.port)] = _server;
120 }
121
122 // We are done connecting
1230 if(self._numberOfServersLeftToInitialize == 0) {
124 // Start ha function if it exists
1250 if(self.haEnabled) {
126 // Setup the ha process
1270 if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId);
1280 self._replicasetTimeoutId = setInterval(self.mongosCheckFunction, self.mongosStatusCheckInterval);
129 }
130
131 // Set the mongos to connected
1320 self._serverState = "connected";
133
134 // Emit the open event
1350 if(self.emitOpen)
1360 self._emitAcrossAllDbInstances(self, null, "open", null, null, null);
137
1380 self._emitAcrossAllDbInstances(self, null, "fullsetup", null, null, null);
139 // Callback
1400 callback(null, self.db);
141 }
142 }
143 };
144
145 // Error handler
1460 var errorOrCloseHandler = function(_server) {
1470 return function(err, result) {
148 // Emit left event, signaling mongos left the ha
1490 self.emit('left', 'mongos', _server);
150 // Execute all the callbacks with errors
1510 self.__executeAllCallbacksWithError(err);
152 // Check if we have the server
1530 var found = false;
154
155 // Get the server name
1560 var server_name = format("%s:%s", _server.host, _server.port);
157 // Add the downed server
1580 self.downServers[server_name] = _server;
159 // Remove the current server from the list
1600 delete self.upServers[server_name];
161
162 // Emit close across all the attached db instances
1630 if(Object.keys(self.upServers).length == 0) {
1640 self._emitAcrossAllDbInstances(self, null, "close", new Error("mongos disconnected, no valid proxies contactable over tcp"), null, null);
165 }
166 }
167 }
168
169 // Mongo function
1700 this.mongosCheckFunction = function() {
171 // Set as not waiting for check event
1720 self._haInProgress = true;
173
174 // Servers down
1750 var numberOfServersLeft = Object.keys(self.downServers).length;
176
177 // Check downed servers
1780 if(numberOfServersLeft > 0) {
1790 for(var name in self.downServers) {
180 // Pop a downed server
1810 var downServer = self.downServers[name];
182 // Set up the connection options for a Mongos
1830 var options = {
184 auto_reconnect: false,
185 returnIsMasterResults: true,
186 slaveOk: true,
187 poolSize: downServer.poolSize,
188 socketOptions: {
189 connectTimeoutMS: self._connectTimeoutMS,
190 socketTimeoutMS: self._socketTimeoutMS
191 }
192 }
193
194 // Create a new server object
1950 var newServer = new Server(downServer.host, downServer.port, options);
196 // Setup the connection function
1970 var connectFunction = function(_db, _server, _options, _callback) {
1980 return function() {
199 // Attempt to connect
2000 _server.connect(_db, _options, function(err, result) {
2010 numberOfServersLeft = numberOfServersLeft - 1;
202
2030 if(err) {
2040 return _callback(err, _server);
205 } else {
206 // Set the new server settings
2070 _server._callBackStore = self._callBackStore;
208
209 // Add server event handlers
2100 _server.on("close", errorOrCloseHandler(_server));
2110 _server.on("timeout", errorOrCloseHandler(_server));
2120 _server.on("error", errorOrCloseHandler(_server));
213
214 // Get a read connection
2150 var _connection = _server.checkoutReader();
216 // Get the start time
2170 var startTime = new Date().getTime();
218
219 // Execute ping command to mark each server with the expected times
2200 self.db.command({ping:1}
221 , {failFast:true, connection:_connection}, function(err, result) {
222 // Get the start time
2230 var endTime = new Date().getTime();
224 // Mark the server with the ping time
2250 _server.runtimeStats['pingMs'] = endTime - startTime;
226 // Execute any waiting reads
2270 self._commandsStore.execute_writes();
2280 self._commandsStore.execute_queries();
229 // Callback
2300 return _callback(null, _server);
231 });
232 }
233 });
234 }
235 }
236
237 // Attempt to connect to the database
2380 connectFunction(self.db, newServer, options, function(err, _server) {
239 // If we have an error
2400 if(err) {
2410 self.downServers[format("%s:%s", _server.host, _server.port)] = _server;
242 }
243
244 // Connection function
2450 var connectionFunction = function(_auth, _connection, _callback) {
2460 var pending = _auth.length();
247
2480 for(var j = 0; j < pending; j++) {
249 // Get the auth object
2500 var _auth = _auth.get(j);
251 // Unpack the parameter
2520 var username = _auth.username;
2530 var password = _auth.password;
2540 var options = {
255 authMechanism: _auth.authMechanism
256 , authSource: _auth.authdb
257 , connection: _connection
258 };
259
260 // If we have changed the service name
2610 if(_auth.gssapiServiceName)
2620 options.gssapiServiceName = _auth.gssapiServiceName;
263
264 // Hold any error
2650 var _error = null;
266 // Authenticate against the credentials
2670 self.db.authenticate(username, password, options, function(err, result) {
2680 _error = err != null ? err : _error;
269 // Adjust the pending authentication
2700 pending = pending - 1;
271 // Finished up
2720 if(pending == 0) _callback(_error ? _error : null, _error ? false : true);
273 });
274 }
275 }
276
277 // Run auths against the connections
2780 if(self.auth.length() > 0) {
2790 var connections = _server.allRawConnections();
2800 var pendingAuthConn = connections.length;
281
282 // No connections we are done
2830 if(connections.length == 0) {
284 // Set ha done
2850 if(numberOfServersLeft == 0) {
2860 self._haInProgress = false;
287 }
288 }
289
290 // Final error object
2910 var finalError = null;
292 // Go over all the connections
2930 for(var j = 0; j < connections.length; j++) {
294
295 // Execute against all the connections
2960 connectionFunction(self.auth, connections[j], function(err, result) {
297 // Pending authentication
2980 pendingAuthConn = pendingAuthConn - 1 ;
299
300 // Save error if any
3010 finalError = err ? err : finalError;
302
303 // If we are done let's finish up
3040 if(pendingAuthConn == 0) {
305 // Set ha done
3060 if(numberOfServersLeft == 0) {
3070 self._haInProgress = false;
308 }
309
3100 if(!err) {
3110 add_server(self, _server);
312 }
313
314 // Execute any waiting reads
3150 self._commandsStore.execute_writes();
3160 self._commandsStore.execute_queries();
317 }
318 });
319 }
320 } else {
3210 if(!err) {
3220 add_server(self, _server);
323 }
324
325 // Set ha done
3260 if(numberOfServersLeft == 0) {
3270 self._haInProgress = false;
328 // Execute any waiting reads
3290 self._commandsStore.execute_writes();
3300 self._commandsStore.execute_queries();
331 }
332 }
333 })();
334 }
335 } else {
3360 self._haInProgress = false;
337 }
338 }
339
340 // Connect all the server instances
3410 for(var i = 0; i < this.servers.length; i++) {
342 // Get the connection
3430 var server = this.servers[i];
3440 server.mongosInstance = this;
345 // Add server event handlers
3460 server.on("close", errorOrCloseHandler(server));
3470 server.on("timeout", errorOrCloseHandler(server));
3480 server.on("error", errorOrCloseHandler(server));
349
350 // Configuration
3510 var options = {
352 slaveOk: true,
353 poolSize: server.poolSize,
354 socketOptions: { connectTimeoutMS: self._connectTimeoutMS },
355 returnIsMasterResults: true
356 }
357
358 // Connect the instance
3590 server.connect(self.db, options, connectHandler(server));
360 }
361}
362
363/**
364 * @ignore
365 * Add a server to the list of up servers and sort them by ping time
366 */
3671var add_server = function(self, _server) {
368 // Emit a new server joined
3690 self.emit('joined', "mongos", null, _server);
370 // Get the server url
3710 var server_key = format("%s:%s", _server.host, _server.port);
372 // Push to list of valid server
3730 self.upServers[server_key] = _server;
374 // Remove the server from the list of downed servers
3750 delete self.downServers[server_key];
376
377 // Sort the keys by ping time
3780 var keys = Object.keys(self.upServers);
3790 var _upServersSorted = {};
3800 var _upServers = []
381
382 // Get all the servers
3830 for(var name in self.upServers) {
3840 _upServers.push(self.upServers[name]);
385 }
386
387 // Sort all the server
3880 _upServers.sort(function(a, b) {
3890 return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs'];
390 });
391
392 // Rebuild the upServer
3930 for(var i = 0; i < _upServers.length; i++) {
3940 _upServersSorted[format("%s:%s", _upServers[i].host, _upServers[i].port)] = _upServers[i];
395 }
396
397 // Set the up servers
3980 self.upServers = _upServersSorted;
399}
400
401/**
402 * @ignore
403 * Just return the currently picked active connection
404 */
4051Mongos.prototype.allServerInstances = function() {
4060 return this.servers;
407}
408
409/**
410 * Always ourselves
411 * @ignore
412 */
4131Mongos.prototype.setReadPreference = function() {}
414
415/**
416 * @ignore
417 */
4181Mongos.prototype.allRawConnections = function() {
419 // Neeed to build a complete list of all raw connections, start with master server
4200 var allConnections = [];
421 // Get all connected connections
4220 for(var name in this.upServers) {
4230 allConnections = allConnections.concat(this.upServers[name].allRawConnections());
424 }
425 // Return all the conections
4260 return allConnections;
427}
428
429/**
430 * @ignore
431 */
4321Mongos.prototype.isConnected = function() {
4330 return Object.keys(this.upServers).length > 0;
434}
435
436/**
437 * @ignore
438 */
4391Mongos.prototype.isAutoReconnect = function() {
4400 return true;
441}
442
443/**
444 * @ignore
445 */
4461Mongos.prototype.canWrite = Mongos.prototype.isConnected;
447
448/**
449 * @ignore
450 */
4511Mongos.prototype.canRead = Mongos.prototype.isConnected;
452
453/**
454 * @ignore
455 */
4561Mongos.prototype.isDestroyed = function() {
4570 return this._serverState == 'destroyed';
458}
459
460/**
461 * @ignore
462 */
4631Mongos.prototype.checkoutWriter = function() {
464 // Checkout a writer
4650 var keys = Object.keys(this.upServers);
466 // console.dir("============================ checkoutWriter :: " + keys.length)
4670 if(keys.length == 0) return null;
468 // console.log("=============== checkoutWriter :: " + this.upServers[keys[0]].checkoutWriter().socketOptions.port)
4690 return this.upServers[keys[0]].checkoutWriter();
470}
471
472/**
473 * @ignore
474 */
4751Mongos.prototype.checkoutReader = function(read) {
476 // console.log("=============== checkoutReader :: read :: " + read);
477 // If read is set to null default to primary
4780 read = read || 'primary'
479 // If we have a read preference object unpack it
4800 if(read != null && typeof read == 'object' && read['_type'] == 'ReadPreference') {
481 // Validate if the object is using a valid mode
4820 if(!read.isValid()) throw new Error("Illegal readPreference mode specified, " + read.mode);
4830 } else if(!ReadPreference.isValid(read)) {
4840 throw new Error("Illegal readPreference mode specified, " + read);
485 }
486
487 // Checkout a writer
4880 var keys = Object.keys(this.upServers);
4890 if(keys.length == 0) return null;
490 // console.log("=============== checkoutReader :: " + this.upServers[keys[0]].checkoutWriter().socketOptions.port)
491 // console.dir(this._commandsStore.commands)
4920 return this.upServers[keys[0]].checkoutWriter();
493}
494
495/**
496 * @ignore
497 */
4981Mongos.prototype.close = function(callback) {
4990 var self = this;
500 // Set server status as disconnected
5010 this._serverState = 'destroyed';
502 // Number of connections to close
5030 var numberOfConnectionsToClose = self.servers.length;
504 // If we have a ha process running kill it
5050 if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId);
5060 self._replicasetTimeoutId = null;
507
508 // Emit close event
5090 processor(function() {
5100 self._emitAcrossAllDbInstances(self, null, "close", null, null, true)
511 });
512
513 // Flush out any remaining call handlers
5140 self._flushAllCallHandlers(utils.toError("Connection Closed By Application"));
515
516 // Close all the up servers
5170 for(var name in this.upServers) {
5180 this.upServers[name].close(function(err, result) {
5190 numberOfConnectionsToClose = numberOfConnectionsToClose - 1;
520
521 // Callback if we have one defined
5220 if(numberOfConnectionsToClose == 0 && typeof callback == 'function') {
5230 callback(null);
524 }
525 });
526 }
527}
528
529/**
530 * @ignore
531 * Return the used state
532 */
5331Mongos.prototype._isUsed = function() {
5340 return this._used;
535}
536
5371exports.Mongos = Mongos;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/read_preference.js

45%
22
10
12
LineHitsSource
1/**
2 * A class representation of the Read Preference.
3 *
4 * Read Preferences
5 * - **ReadPreference.PRIMARY**, Read from primary only. All operations produce an error (throw an exception where applicable) if primary is unavailable. Cannot be combined with tags (This is the default.).
6 * - **ReadPreference.PRIMARY_PREFERRED**, Read from primary if available, otherwise a secondary.
7 * - **ReadPreference.SECONDARY**, Read from secondary if available, otherwise error.
8 * - **ReadPreference.SECONDARY_PREFERRED**, Read from a secondary if available, otherwise read from the primary.
9 * - **ReadPreference.NEAREST**, All modes read from among the nearest candidates, but unlike other modes, NEAREST will include both the primary and all secondaries in the random selection.
10 *
11 * @class Represents a Read Preference.
12 * @param {String} the read preference type
13 * @param {Object} tags
14 * @return {ReadPreference}
15 */
161var ReadPreference = function(mode, tags) {
170 if(!(this instanceof ReadPreference))
180 return new ReadPreference(mode, tags);
190 this._type = 'ReadPreference';
200 this.mode = mode;
210 this.tags = tags;
22}
23
24/**
25 * @ignore
26 */
271ReadPreference.isValid = function(_mode) {
280 return (_mode == ReadPreference.PRIMARY || _mode == ReadPreference.PRIMARY_PREFERRED
29 || _mode == ReadPreference.SECONDARY || _mode == ReadPreference.SECONDARY_PREFERRED
30 || _mode == ReadPreference.NEAREST
31 || _mode == true || _mode == false);
32}
33
34/**
35 * @ignore
36 */
371ReadPreference.prototype.isValid = function(mode) {
380 var _mode = typeof mode == 'string' ? mode : this.mode;
390 return ReadPreference.isValid(_mode);
40}
41
42/**
43 * @ignore
44 */
451ReadPreference.prototype.toObject = function() {
460 var object = {mode:this.mode};
47
480 if(this.tags != null) {
490 object['tags'] = this.tags;
50 }
51
520 return object;
53}
54
55/**
56 * @ignore
57 */
581ReadPreference.PRIMARY = 'primary';
591ReadPreference.PRIMARY_PREFERRED = 'primaryPreferred';
601ReadPreference.SECONDARY = 'secondary';
611ReadPreference.SECONDARY_PREFERRED = 'secondaryPreferred';
621ReadPreference.NEAREST = 'nearest'
63
64/**
65 * @ignore
66 */
671exports.ReadPreference = ReadPreference;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js

6%
196
13
183
LineHitsSource
11var DbCommand = require('../../commands/db_command').DbCommand
2 , format = require('util').format;
3
41var HighAvailabilityProcess = function(replset, options) {
50 this.replset = replset;
60 this.options = options;
70 this.server = null;
80 this.state = HighAvailabilityProcess.INIT;
90 this.selectedIndex = 0;
10}
11
121HighAvailabilityProcess.INIT = 'init';
131HighAvailabilityProcess.RUNNING = 'running';
141HighAvailabilityProcess.STOPPED = 'stopped';
15
161HighAvailabilityProcess.prototype.start = function() {
170 var self = this;
180 if(this.replset._state
19 && Object.keys(this.replset._state.addresses).length == 0) {
200 if(this.server) this.server.close();
210 this.state = HighAvailabilityProcess.STOPPED;
220 return;
23 }
24
250 if(this.server) this.server.close();
26 // Start the running
270 this._haProcessInProcess = false;
280 this.state = HighAvailabilityProcess.RUNNING;
29
30 // Get all possible reader servers
310 var candidate_servers = this.replset._state.getAllReadServers();
320 if(candidate_servers.length == 0) {
330 return;
34 }
35
36 // Select a candidate server for the connection
370 var server = candidate_servers[this.selectedIndex % candidate_servers.length];
380 this.selectedIndex = this.selectedIndex + 1;
39
40 // Unpack connection options
410 var connectTimeoutMS = self.options.connectTimeoutMS || 10000;
420 var socketTimeoutMS = self.options.socketTimeoutMS || 30000;
43
44 // Just ensure we don't have a full cycle dependency
450 var Db = require('../../db').Db
460 var Server = require('../server').Server;
47
48 // Set up a new server instance
490 var newServer = new Server(server.host, server.port, {
50 auto_reconnect: false
51 , returnIsMasterResults: true
52 , poolSize: 1
53 , socketOptions: {
54 connectTimeoutMS: connectTimeoutMS,
55 socketTimeoutMS: socketTimeoutMS,
56 keepAlive: 100
57 }
58 , ssl: this.options.ssl
59 , sslValidate: this.options.sslValidate
60 , sslCA: this.options.sslCA
61 , sslCert: this.options.sslCert
62 , sslKey: this.options.sslKey
63 , sslPass: this.options.sslPass
64 });
65
66 // Create new dummy db for app
670 self.db = new Db('local', newServer, {w:1});
68
69 // Set up the event listeners
700 newServer.once("error", _handle(this, newServer));
710 newServer.once("close", _handle(this, newServer));
720 newServer.once("timeout", _handle(this, newServer));
730 newServer.name = format("%s:%s", server.host, server.port);
74
75 // Let's attempt a connection over here
760 newServer.connect(self.db, function(err, result, _server) {
770 if(self.state == HighAvailabilityProcess.STOPPED) {
780 _server.close();
79 }
80
810 if(err) {
82 // Close the server
830 _server.close();
84 // Check if we can even do HA (is there anything running)
850 if(Object.keys(self.replset._state.addresses).length == 0) {
860 return;
87 }
88
89 // Let's boot the ha timeout settings
900 setTimeout(function() {
910 self.start();
92 }, self.options.haInterval);
93 } else {
940 self.server = _server;
95 // Let's boot the ha timeout settings
960 setTimeout(_timeoutHandle(self), self.options.haInterval);
97 }
98 });
99}
100
1011HighAvailabilityProcess.prototype.stop = function() {
1020 this.state = HighAvailabilityProcess.STOPPED;
1030 if(this.server) this.server.close();
104}
105
1061var _timeoutHandle = function(self) {
1070 return function() {
1080 if(self.state == HighAvailabilityProcess.STOPPED) {
109 // Stop all server instances
1100 for(var name in self.replset._state.addresses) {
1110 self.replset._state.addresses[name].close();
1120 delete self.replset._state.addresses[name];
113 }
114
115 // Finished pinging
1160 return;
117 }
118
119 // If the server is connected
1200 if(self.server.isConnected() && !self._haProcessInProcess) {
121 // Start HA process
1220 self._haProcessInProcess = true;
123 // Execute is master command
1240 self.db._executeQueryCommand(DbCommand.createIsMasterCommand(self.db),
125 {failFast:true, connection: self.server.checkoutReader()}
126 , function(err, res) {
1270 if(err) {
1280 self.server.close();
1290 return setTimeout(_timeoutHandle(self), self.options.haInterval);
130 }
131
132 // Master document
1330 var master = res.documents[0];
1340 var hosts = master.hosts || [];
1350 var reconnect_servers = [];
1360 var state = self.replset._state;
137
138 // We are in recovery mode, let's remove the current server
1390 if(!master.ismaster
140 && !master.secondary
141 && state.addresses[master.me]) {
1420 self.server.close();
1430 state.addresses[master.me].close();
1440 delete state.secondaries[master.me];
1450 return setTimeout(_timeoutHandle(self), self.options.haInterval);
146 }
147
148 // For all the hosts let's check that we have connections
1490 for(var i = 0; i < hosts.length; i++) {
1500 var host = hosts[i];
151 // Check if we need to reconnect to a server
1520 if(state.addresses[host] == null) {
1530 reconnect_servers.push(host);
1540 } else if(state.addresses[host] && !state.addresses[host].isConnected()) {
1550 state.addresses[host].close();
1560 delete state.secondaries[host];
1570 reconnect_servers.push(host);
158 }
159
1600 if((master.primary && state.master == null)
161 || (master.primary && state.master.name != master.primary)) {
162
163 // Locate the primary and set it
1640 if(state.addresses[master.primary]) {
1650 if(state.master) state.master.close();
1660 delete state.secondaries[master.primary];
1670 state.master = state.addresses[master.primary];
168 }
169
170 // Set up the changes
1710 if(state.master != null && state.master.isMasterDoc != null) {
1720 state.master.isMasterDoc.ismaster = true;
1730 state.master.isMasterDoc.secondary = false;
1740 } else if(state.master != null) {
1750 state.master.isMasterDoc = master;
1760 state.master.isMasterDoc.ismaster = true;
1770 state.master.isMasterDoc.secondary = false;
178 }
179
180 // Execute any waiting commands (queries or writes)
1810 self.replset._commandsStore.execute_queries();
1820 self.replset._commandsStore.execute_writes();
183 }
184 }
185
186 // Let's reconnect to any server needed
1870 if(reconnect_servers.length > 0) {
1880 _reconnect_servers(self, reconnect_servers);
189 } else {
1900 self._haProcessInProcess = false
1910 return setTimeout(_timeoutHandle(self), self.options.haInterval);
192 }
193 });
1940 } else if(!self.server.isConnected()) {
1950 setTimeout(function() {
1960 return self.start();
197 }, self.options.haInterval);
198 } else {
1990 setTimeout(_timeoutHandle(self), self.options.haInterval);
200 }
201 }
202}
203
2041var _reconnect_servers = function(self, reconnect_servers) {
2050 if(reconnect_servers.length == 0) {
2060 self._haProcessInProcess = false
2070 return setTimeout(_timeoutHandle(self), self.options.haInterval);
208 }
209
210 // Unpack connection options
2110 var connectTimeoutMS = self.options.connectTimeoutMS || 10000;
2120 var socketTimeoutMS = self.options.socketTimeoutMS || 0;
213
214 // Server class
2150 var Db = require('../../db').Db
2160 var Server = require('../server').Server;
217 // Get the host
2180 var host = reconnect_servers.shift();
219 // Split it up
2200 var _host = host.split(":")[0];
2210 var _port = parseInt(host.split(":")[1], 10);
222
223 // Set up a new server instance
2240 var newServer = new Server(_host, _port, {
225 auto_reconnect: false
226 , returnIsMasterResults: true
227 , poolSize: self.options.poolSize
228 , socketOptions: {
229 connectTimeoutMS: connectTimeoutMS,
230 socketTimeoutMS: socketTimeoutMS
231 }
232 , ssl: self.options.ssl
233 , sslValidate: self.options.sslValidate
234 , sslCA: self.options.sslCA
235 , sslCert: self.options.sslCert
236 , sslKey: self.options.sslKey
237 , sslPass: self.options.sslPass
238 });
239
240 // Create new dummy db for app
2410 var db = new Db('local', newServer, {w:1});
2420 var state = self.replset._state;
243
244 // Set up the event listeners
2450 newServer.once("error", _repl_set_handler("error", self.replset, newServer));
2460 newServer.once("close", _repl_set_handler("close", self.replset, newServer));
2470 newServer.once("timeout", _repl_set_handler("timeout", self.replset, newServer));
248
249 // Set shared state
2500 newServer.name = host;
2510 newServer._callBackStore = self.replset._callBackStore;
2520 newServer.replicasetInstance = self.replset;
2530 newServer.enableRecordQueryStats(self.replset.recordQueryStats);
254
255 // Let's attempt a connection over here
2560 newServer.connect(db, function(err, result, _server) {
2570 if(self.state == HighAvailabilityProcess.STOPPED) {
2580 _server.close();
259 }
260
261 // If we connected let's check what kind of server we have
2620 if(!err) {
2630 _apply_auths(self, db, _server, function(err, result) {
2640 if(err) {
2650 _server.close();
266 // Process the next server
2670 return setTimeout(function() {
2680 _reconnect_servers(self, reconnect_servers);
269 }, self.options.haInterval);
270 }
2710 var doc = _server.isMasterDoc;
272 // Fire error on any unknown callbacks for this server
2730 self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err);
274
2750 if(doc.ismaster) {
276 // Emit primary added
2770 self.replset.emit('joined', "primary", doc, _server);
278
279 // If it was a secondary remove it
2800 if(state.secondaries[doc.me]) {
2810 delete state.secondaries[doc.me];
282 }
283
284 // Override any server in list of addresses
2850 state.addresses[doc.me] = _server;
286 // Set server as master
2870 state.master = _server;
288 // Execute any waiting writes
2890 self.replset._commandsStore.execute_writes();
2900 } else if(doc.secondary) {
291 // Emit secondary added
2920 self.replset.emit('joined', "secondary", doc, _server);
293 // Add the secondary to the state
2940 state.secondaries[doc.me] = _server;
295 // Override any server in list of addresses
2960 state.addresses[doc.me] = _server;
297 // Execute any waiting reads
2980 self.replset._commandsStore.execute_queries();
299 } else {
3000 _server.close();
301 }
302
303 // Set any tags on the instance server
3040 _server.name = doc.me;
3050 _server.tags = doc.tags;
306 // Process the next server
3070 setTimeout(function() {
3080 _reconnect_servers(self, reconnect_servers);
309 }, self.options.haInterval);
310 });
311 } else {
3120 _server.close();
3130 self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err);
314
3150 setTimeout(function() {
3160 _reconnect_servers(self, reconnect_servers);
317 }, self.options.haInterval);
318 }
319 });
320}
321
3221var _apply_auths = function(self, _db, _server, _callback) {
3230 if(self.replset.auth.length() == 0) return _callback(null);
324 // Apply any authentication needed
3250 if(self.replset.auth.length() > 0) {
3260 var pending = self.replset.auth.length();
3270 var connections = _server.allRawConnections();
3280 var pendingAuthConn = connections.length;
329
330 // Connection function
3310 var connectionFunction = function(_auth, _connection, __callback) {
3320 var pending = _auth.length();
333
3340 for(var j = 0; j < pending; j++) {
335 // Get the auth object
3360 var _auth = _auth.get(j);
337 // Unpack the parameter
3380 var username = _auth.username;
3390 var password = _auth.password;
3400 var options = {
341 authMechanism: _auth.authMechanism
342 , authSource: _auth.authdb
343 , connection: _connection
344 };
345
346 // If we have changed the service name
3470 if(_auth.gssapiServiceName)
3480 options.gssapiServiceName = _auth.gssapiServiceName;
349
350 // Hold any error
3510 var _error = null;
352
353 // Authenticate against the credentials
3540 _db.authenticate(username, password, options, function(err, result) {
3550 _error = err != null ? err : _error;
356 // Adjust the pending authentication
3570 pending = pending - 1;
358 // Finished up
3590 if(pending == 0) __callback(_error ? _error : null, _error ? false : true);
360 });
361 }
362 }
363
364 // Final error object
3650 var finalError = null;
366 // Iterate over all the connections
3670 for(var i = 0; i < connections.length; i++) {
3680 connectionFunction(self.replset.auth, connections[i], function(err, result) {
369 // Pending authentication
3700 pendingAuthConn = pendingAuthConn - 1 ;
371
372 // Save error if any
3730 finalError = err ? err : finalError;
374
375 // If we are done let's finish up
3760 if(pendingAuthConn == 0) {
3770 _callback(null);
378 }
379 });
380 }
381 }
382}
383
3841var _handle = function(self, server) {
3850 return function(err) {
3860 server.close();
387 }
388}
389
3901var _repl_set_handler = function(event, self, server) {
3910 var ReplSet = require('./repl_set').ReplSet;
392
3930 return function(err, doc) {
3940 server.close();
395
396 // The event happened to a primary
397 // Remove it from play
3980 if(self._state.isPrimary(server)) {
3990 self._state.master == null;
4000 self._serverState = ReplSet.REPLSET_READ_ONLY;
4010 } else if(self._state.isSecondary(server)) {
4020 delete self._state.secondaries[server.name];
403 }
404
405 // Unpack variables
4060 var host = server.socketOptions.host;
4070 var port = server.socketOptions.port;
408
409 // Fire error on any unknown callbacks
4100 self.__executeAllServerSpecificErrorCallbacks(host, port, err);
411 }
412}
413
4141exports.HighAvailabilityProcess = HighAvailabilityProcess;
415

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js

7%
66
5
61
LineHitsSource
11var PingStrategy = require('./strategies/ping_strategy').PingStrategy
2 , StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy
3 , ReadPreference = require('../read_preference').ReadPreference;
4
51var Options = function(options) {
60 options = options || {};
70 this._options = options;
80 this.ha = options.ha || true;
90 this.haInterval = options.haInterval || 2000;
100 this.reconnectWait = options.reconnectWait || 1000;
110 this.retries = options.retries || 30;
120 this.rs_name = options.rs_name;
130 this.socketOptions = options.socketOptions || {};
140 this.readPreference = options.readPreference;
150 this.readSecondary = options.read_secondary;
160 this.poolSize = options.poolSize == null ? 5 : options.poolSize;
170 this.strategy = options.strategy || 'ping';
180 this.secondaryAcceptableLatencyMS = options.secondaryAcceptableLatencyMS || 15;
190 this.connectArbiter = options.connectArbiter || false;
200 this.connectWithNoPrimary = options.connectWithNoPrimary || false;
210 this.logger = options.logger;
220 this.ssl = options.ssl || false;
230 this.sslValidate = options.sslValidate || false;
240 this.sslCA = options.sslCA;
250 this.sslCert = options.sslCert;
260 this.sslKey = options.sslKey;
270 this.sslPass = options.sslPass;
280 this.emitOpen = options.emitOpen || true;
29}
30
311Options.prototype.init = function() {
320 if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) {
330 throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate");
34 }
35
36 // Make sure strategy is one of the two allowed
370 if(this.strategy != null && (this.strategy != 'ping' && this.strategy != 'statistical' && this.strategy != 'none'))
380 throw new Error("Only ping or statistical strategies allowed");
39
400 if(this.strategy == null) this.strategy = 'ping';
41
42 // Set logger if strategy exists
430 if(this.strategyInstance) this.strategyInstance.logger = this.logger;
44
45 // Unpack read Preference
460 var readPreference = this.readPreference;
47 // Validate correctness of Read preferences
480 if(readPreference != null) {
490 if(readPreference != ReadPreference.PRIMARY && readPreference != ReadPreference.PRIMARY_PREFERRED
50 && readPreference != ReadPreference.SECONDARY && readPreference != ReadPreference.SECONDARY_PREFERRED
51 && readPreference != ReadPreference.NEAREST && typeof readPreference != 'object' && readPreference['_type'] != 'ReadPreference') {
520 throw new Error("Illegal readPreference mode specified, " + readPreference);
53 }
54
550 this.readPreference = readPreference;
56 } else {
570 this.readPreference = null;
58 }
59
60 // Ensure read_secondary is set correctly
610 if(this.readSecondary != null)
620 this.readSecondary = this.readPreference == ReadPreference.PRIMARY
63 || this.readPreference == false
64 || this.readPreference == null ? false : true;
65
66 // Ensure correct slave set
670 if(this.readSecondary) this.slaveOk = true;
68
69 // Set up logger if any set
700 this.logger = this.logger != null
71 && (typeof this.logger.debug == 'function')
72 && (typeof this.logger.error == 'function')
73 && (typeof this.logger.debug == 'function')
74 ? this.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}};
75
76 // Connection timeout
770 this.connectTimeoutMS = this.socketOptions.connectTimeoutMS
78 ? this.socketOptions.connectTimeoutMS
79 : 1000;
80
81 // Socket connection timeout
820 this.socketTimeoutMS = this.socketOptions.socketTimeoutMS
83 ? this.socketOptions.socketTimeoutMS
84 : 30000;
85}
86
871Options.prototype.decorateAndClean = function(servers, callBackStore) {
880 var self = this;
89
90 // var de duplicate list
910 var uniqueServers = {};
92 // De-duplicate any servers in the seed list
930 for(var i = 0; i < servers.length; i++) {
940 var server = servers[i];
95 // If server does not exist set it
960 if(uniqueServers[server.host + ":" + server.port] == null) {
970 uniqueServers[server.host + ":" + server.port] = server;
98 }
99 }
100
101 // Let's set the deduplicated list of servers
1020 var finalServers = [];
103 // Add the servers
1040 for(var key in uniqueServers) {
1050 finalServers.push(uniqueServers[key]);
106 }
107
1080 finalServers.forEach(function(server) {
109 // Ensure no server has reconnect on
1100 server.options.auto_reconnect = false;
111 // Set up ssl options
1120 server.ssl = self.ssl;
1130 server.sslValidate = self.sslValidate;
1140 server.sslCA = self.sslCA;
1150 server.sslCert = self.sslCert;
1160 server.sslKey = self.sslKey;
1170 server.sslPass = self.sslPass;
1180 server.poolSize = self.poolSize;
119 // Set callback store
1200 server._callBackStore = callBackStore;
121 });
122
1230 return finalServers;
124}
125
1261exports.Options = Options;
127

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js

13%
338
44
294
LineHitsSource
11var ReadPreference = require('../read_preference').ReadPreference
2 , DbCommand = require('../../commands/db_command').DbCommand
3 , inherits = require('util').inherits
4 , format = require('util').format
5 , timers = require('timers')
6 , Server = require('../server').Server
7 , utils = require('../../utils')
8 , PingStrategy = require('./strategies/ping_strategy').PingStrategy
9 , StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy
10 , Options = require('./options').Options
11 , ReplSetState = require('./repl_set_state').ReplSetState
12 , HighAvailabilityProcess = require('./ha').HighAvailabilityProcess
13 , Base = require('../base').Base;
14
151var STATE_STARTING_PHASE_1 = 0;
161var STATE_PRIMARY = 1;
171var STATE_SECONDARY = 2;
181var STATE_RECOVERING = 3;
191var STATE_FATAL_ERROR = 4;
201var STATE_STARTING_PHASE_2 = 5;
211var STATE_UNKNOWN = 6;
221var STATE_ARBITER = 7;
231var STATE_DOWN = 8;
241var STATE_ROLLBACK = 9;
25
26// Set processor, setImmediate if 0.10 otherwise nextTick
271var processor = require('../../utils').processor();
28
29/**
30 * ReplSet constructor provides replicaset functionality
31 *
32 * Options
33 * - **ha** {Boolean, default:true}, turn on high availability.
34 * - **haInterval** {Number, default:2000}, time between each replicaset status check.
35 * - **reconnectWait** {Number, default:1000}, time to wait in miliseconds before attempting reconnect.
36 * - **retries** {Number, default:30}, number of times to attempt a replicaset reconnect.
37 * - **rs_name** {String}, the name of the replicaset to connect to.
38 * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number))
39 * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
40 * - **strategy** {String, default:'ping'}, selection strategy for reads choose between (ping, statistical and none, default is ping)
41 * - **secondaryAcceptableLatencyMS** {Number, default:15}, sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms)
42 * - **connectWithNoPrimary** {Boolean, default:false}, sets if the driver should connect even if no primary is available
43 * - **connectArbiter** {Boolean, default:false}, sets if the driver should connect to arbiters or not.
44 * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**.
45 * - **poolSize** {Number, default:5}, number of connections in the connection pool for each server instance, set to 5 as default for legacy reasons.
46 * - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support)
47 * - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
48 * - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
49 * - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
50 * - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
51 * - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher)
52 *
53 * @class Represents a
54 Replicaset Configuration
55 * @param {Array} list of server objects participating in the replicaset.
56 * @param {Object} [options] additional options for the replicaset connection.
57 */
581var ReplSet = exports.ReplSet = function(servers, options) {
59 // Set up basic
600 if(!(this instanceof ReplSet))
610 return new ReplSet(servers, options);
62
63 // Set up event emitter
640 Base.call(this);
65
66 // Ensure we have a list of servers
670 if(!Array.isArray(servers)) throw Error("The parameter must be an array of servers and contain at least one server");
68 // Ensure no Mongos's
690 for(var i = 0; i < servers.length; i++) {
700 if(!(servers[i] instanceof Server)) throw new Error("list of servers must be of type Server");
71 }
72
73 // Save the options
740 this.options = new Options(options);
75 // Ensure basic validation of options
760 this.options.init();
77
78 // Server state
790 this._serverState = ReplSet.REPLSET_DISCONNECTED;
80 // Add high availability process
810 this._haProcess = new HighAvailabilityProcess(this, this.options);
82
83 // Let's iterate over all the provided server objects and decorate them
840 this.servers = this.options.decorateAndClean(servers, this._callBackStore);
85 // Throw error if no seed servers
860 if(this.servers.length == 0) throw new Error("No valid seed servers in the array");
87
88 // Let's set up our strategy object for picking secondaries
890 if(this.options.strategy == 'ping') {
90 // Create a new instance
910 this.strategyInstance = new PingStrategy(this, this.options.secondaryAcceptableLatencyMS);
920 } else if(this.options.strategy == 'statistical') {
93 // Set strategy as statistical
940 this.strategyInstance = new StatisticsStrategy(this);
95 // Add enable query information
960 this.enableRecordQueryStats(true);
97 }
98
990 this.emitOpen = this.options.emitOpen || true;
100 // Set up a clean state
1010 this._state = new ReplSetState(this);
102 // Current round robin selected server
1030 this._currentServerChoice = 0;
104 // Ensure up the server callbacks
1050 for(var i = 0; i < this.servers.length; i++) {
1060 this.servers[i]._callBackStore = this._callBackStore;
1070 this.servers[i].name = format("%s:%s", this.servers[i].host, this.servers[i].port)
1080 this.servers[i].replicasetInstance = this;
1090 this.servers[i].options.auto_reconnect = false;
1100 this.servers[i].inheritReplSetOptionsFrom(this);
111 }
112
113 // Allow setting the socketTimeoutMS on all connections
114 // to work around issues such as secondaries blocking due to compaction
1150 utils.setSocketTimeoutProperty(this, this.options.socketOptions);
116}
117
118/**
119 * @ignore
120 */
1211inherits(ReplSet, Base);
122
123// Replicaset states
1241ReplSet.REPLSET_CONNECTING = 'connecting';
1251ReplSet.REPLSET_DISCONNECTED = 'disconnected';
1261ReplSet.REPLSET_CONNECTED = 'connected';
1271ReplSet.REPLSET_RECONNECTING = 'reconnecting';
1281ReplSet.REPLSET_DESTROYED = 'destroyed';
1291ReplSet.REPLSET_READ_ONLY = 'readonly';
130
1311ReplSet.prototype.isAutoReconnect = function() {
1320 return true;
133}
134
1351ReplSet.prototype.canWrite = function() {
1360 return this._state.master && this._state.master.isConnected();
137}
138
1391ReplSet.prototype.canRead = function(read) {
1400 if((read == ReadPreference.PRIMARY
1410 || read == null || read == false) && (this._state.master == null || !this._state.master.isConnected())) return false;
1420 return Object.keys(this._state.secondaries).length > 0;
143}
144
145/**
146 * @ignore
147 */
1481ReplSet.prototype.enableRecordQueryStats = function(enable) {
149 // Set the global enable record query stats
1500 this.recordQueryStats = enable;
151
152 // Enable all the servers
1530 for(var i = 0; i < this.servers.length; i++) {
1540 this.servers[i].enableRecordQueryStats(enable);
155 }
156}
157
158/**
159 * @ignore
160 */
1611ReplSet.prototype.setReadPreference = function(preference) {
1620 this.options.readPreference = preference;
163}
164
1651ReplSet.prototype.connect = function(parent, options, callback) {
1660 if(this._serverState != ReplSet.REPLSET_DISCONNECTED)
1670 return callback(new Error("in process of connection"));
168
169 // If no callback throw
1700 if(!(typeof callback == 'function'))
1710 throw new Error("cannot call ReplSet.prototype.connect with no callback function");
172
1730 var self = this;
174 // Save db reference
1750 this.options.db = parent;
176 // Set replicaset as connecting
1770 this._serverState = ReplSet.REPLSET_CONNECTING
178 // Copy all the servers to our list of seeds
1790 var candidateServers = this.servers.slice(0);
180 // Pop the first server
1810 var server = candidateServers.pop();
1820 server.name = format("%s:%s", server.host, server.port);
183 // Set up the options
1840 var opts = {
185 returnIsMasterResults: true,
186 eventReceiver: server
187 }
188
189 // Register some event listeners
1900 this.once("fullsetup", function(err, db, replset) {
191 // Set state to connected
1920 self._serverState = ReplSet.REPLSET_CONNECTED;
193 // Stop any process running
1940 if(self._haProcess) self._haProcess.stop();
195 // Start the HA process
1960 self._haProcess.start();
197
198 // Emit fullsetup
1990 processor(function() {
2000 if(self.emitOpen)
2010 self._emitAcrossAllDbInstances(self, null, "open", null, null, null);
202
2030 self._emitAcrossAllDbInstances(self, null, "fullsetup", null, null, null);
204 });
205
206 // If we have a strategy defined start it
2070 if(self.strategyInstance) {
2080 self.strategyInstance.start();
209 }
210
211 // Finishing up the call
2120 callback(err, db, replset);
213 });
214
215 // Errors
2160 this.once("connectionError", function(err, result) {
2170 callback(err, result);
218 });
219
220 // Attempt to connect to the server
2210 server.connect(this.options.db, opts, _connectHandler(this, candidateServers, server));
222}
223
2241ReplSet.prototype.close = function(callback) {
2250 var self = this;
226 // Set as destroyed
2270 this._serverState = ReplSet.REPLSET_DESTROYED;
228 // Stop the ha
2290 this._haProcess.stop();
230
231 // If we have a strategy stop it
2320 if(this.strategyInstance) {
2330 this.strategyInstance.stop();
234 }
235
236 // Kill all servers available
2370 for(var name in this._state.addresses) {
2380 this._state.addresses[name].close();
239 }
240
241 // Clean out the state
2420 this._state = new ReplSetState(this);
243
244 // Emit close event
2450 processor(function() {
2460 self._emitAcrossAllDbInstances(self, null, "close", null, null, true)
247 });
248
249 // Flush out any remaining call handlers
2500 self._flushAllCallHandlers(utils.toError("Connection Closed By Application"));
251
252 // Callback
2530 if(typeof callback == 'function')
2540 return callback(null, null);
255}
256
257/**
258 * Creates a new server for the `replset` based on `host`.
259 *
260 * @param {String} host - host:port pair (localhost:27017)
261 * @param {ReplSet} replset - the ReplSet instance
262 * @return {Server}
263 * @ignore
264 */
2651var createServer = function(self, host, options) {
266 // copy existing socket options to new server
2670 var socketOptions = {}
2680 if(options.socketOptions) {
2690 var keys = Object.keys(options.socketOptions);
2700 for(var k = 0; k < keys.length; k++) {
2710 socketOptions[keys[k]] = options.socketOptions[keys[k]];
272 }
273 }
274
2750 var parts = host.split(/:/);
2760 if(1 === parts.length) {
2770 parts[1] = Connection.DEFAULT_PORT;
278 }
279
2800 socketOptions.host = parts[0];
2810 socketOptions.port = parseInt(parts[1], 10);
282
2830 var serverOptions = {
284 readPreference: options.readPreference,
285 socketOptions: socketOptions,
286 poolSize: options.poolSize,
287 logger: options.logger,
288 auto_reconnect: false,
289 ssl: options.ssl,
290 sslValidate: options.sslValidate,
291 sslCA: options.sslCA,
292 sslCert: options.sslCert,
293 sslKey: options.sslKey,
294 sslPass: options.sslPass
295 }
296
2970 var server = new Server(socketOptions.host, socketOptions.port, serverOptions);
298 // Set up shared state
2990 server._callBackStore = self._callBackStore;
3000 server.replicasetInstance = self;
3010 server.enableRecordQueryStats(self.recordQueryStats);
302 // Set up event handlers
3030 server.on("close", _handler("close", self, server));
3040 server.on("error", _handler("error", self, server));
3050 server.on("timeout", _handler("timeout", self, server));
3060 return server;
307}
308
3091var _handler = function(event, self, server) {
3100 return function(err, doc) {
311 // The event happened to a primary
312 // Remove it from play
3130 if(self._state.isPrimary(server)) {
314 // Emit that the primary left the replicaset
3150 self.emit('left', 'primary', server);
316 // Get the current master
3170 var current_master = self._state.master;
3180 self._state.master = null;
3190 self._serverState = ReplSet.REPLSET_READ_ONLY;
320
3210 if(current_master != null) {
322 // Unpack variables
3230 var host = current_master.socketOptions.host;
3240 var port = current_master.socketOptions.port;
325
326 // Fire error on any unknown callbacks
3270 self.__executeAllServerSpecificErrorCallbacks(host, port, err);
328 }
3290 } else if(self._state.isSecondary(server)) {
330 // Emit that a secondary left the replicaset
3310 self.emit('left', 'secondary', server);
332 // Delete from the list
3330 delete self._state.secondaries[server.name];
334 }
335
336 // If there is no more connections left and the setting is not destroyed
337 // set to disconnected
3380 if(Object.keys(self._state.addresses).length == 0
339 && self._serverState != ReplSet.REPLSET_DESTROYED) {
3400 self._serverState = ReplSet.REPLSET_DISCONNECTED;
341
342 // Emit close across all the attached db instances
3430 self._dbStore.emit("close", new Error("replicaset disconnected, no valid servers contactable over tcp"), null, true);
344 }
345
346 // Unpack variables
3470 var host = server.socketOptions.host;
3480 var port = server.socketOptions.port;
349
350 // Fire error on any unknown callbacks
3510 self.__executeAllServerSpecificErrorCallbacks(host, port, err);
352 }
353}
354
3551var locateNewServers = function(self, state, candidateServers, ismaster) {
356 // Retrieve the host
3570 var hosts = ismaster.hosts;
358 // In candidate servers
3590 var inCandidateServers = function(name, candidateServers) {
3600 for(var i = 0; i < candidateServers.length; i++) {
3610 if(candidateServers[i].name == name) return true;
362 }
363
3640 return false;
365 }
366
367 // New servers
3680 var newServers = [];
3690 if(Array.isArray(hosts)) {
370 // Let's go over all the hosts
3710 for(var i = 0; i < hosts.length; i++) {
3720 if(!state.contains(hosts[i])
373 && !inCandidateServers(hosts[i], candidateServers)) {
3740 newServers.push(createServer(self, hosts[i], self.options));
375 }
376 }
377 }
378
379 // Return list of possible new servers
3800 return newServers;
381}
382
3831var _connectHandler = function(self, candidateServers, instanceServer) {
3840 return function(err, doc) {
385 // If we have an error add to the list
3860 if(err) {
3870 self._state.errors[instanceServer.name] = instanceServer;
388 } else {
3890 delete self._state.errors[instanceServer.name];
390 }
391
3920 if(!err) {
3930 var ismaster = doc.documents[0]
394
395 // Error the server if
3960 if(!ismaster.ismaster
397 && !ismaster.secondary) {
3980 self._state.errors[instanceServer.name] = instanceServer;
399 }
400 }
401
402
403 // No error let's analyse the ismaster command
4040 if(!err && self._state.errors[instanceServer.name] == null) {
4050 var ismaster = doc.documents[0]
406
407 // If no replicaset name exists set the current one
4080 if(self.options.rs_name == null) {
4090 self.options.rs_name = ismaster.setName;
410 }
411
412 // If we have a member that is not part of the set let's finish up
4130 if(typeof ismaster.setName == 'string' && ismaster.setName != self.options.rs_name) {
4140 return self.emit("connectionError", new Error("Replicaset name " + ismaster.setName + " does not match specified name " + self.options.rs_name));
415 }
416
417 // Add the error handlers
4180 instanceServer.on("close", _handler("close", self, instanceServer));
4190 instanceServer.on("error", _handler("error", self, instanceServer));
4200 instanceServer.on("timeout", _handler("timeout", self, instanceServer));
421
422 // Set any tags on the instance server
4230 instanceServer.name = ismaster.me;
4240 instanceServer.tags = ismaster.tags;
425
426 // Add the server to the list
4270 self._state.addServer(instanceServer, ismaster);
428
429 // Check if we have more servers to add (only check when done with initial set)
4300 if(candidateServers.length == 0) {
431 // Get additional new servers that are not currently in set
4320 var new_servers = locateNewServers(self, self._state, candidateServers, ismaster);
433
434 // Locate any new servers that have not errored out yet
4350 for(var i = 0; i < new_servers.length; i++) {
4360 if(self._state.errors[new_servers[i].name] == null) {
4370 candidateServers.push(new_servers[i])
438 }
439 }
440 }
441 }
442
443 // If the candidate server list is empty and no valid servers
4440 if(candidateServers.length == 0 &&
445 !self._state.hasValidServers()) {
4460 return self.emit("connectionError", new Error("No valid replicaset instance servers found"));
4470 } else if(candidateServers.length == 0) {
4480 if(!self.options.connectWithNoPrimary && (self._state.master == null || !self._state.master.isConnected())) {
4490 return self.emit("connectionError", new Error("No primary found in set"));
450 }
4510 return self.emit("fullsetup", null, self.options.db, self);
452 }
453
454 // Let's connect the next server
4550 var nextServer = candidateServers.pop();
456
457 // Set up the options
4580 var opts = {
459 returnIsMasterResults: true,
460 eventReceiver: nextServer
461 }
462
463 // Attempt to connect to the server
4640 nextServer.connect(self.options.db, opts, _connectHandler(self, candidateServers, nextServer));
465 }
466}
467
4681ReplSet.prototype.isDestroyed = function() {
4690 return this._serverState == ReplSet.REPLSET_DESTROYED;
470}
471
4721ReplSet.prototype.isConnected = function(read) {
4730 var isConnected = false;
474
4750 if(read == null || read == ReadPreference.PRIMARY || read == false)
4760 isConnected = this._state.master != null && this._state.master.isConnected();
477
4780 if((read == ReadPreference.PRIMARY_PREFERRED || read == ReadPreference.SECONDARY_PREFERRED || read == ReadPreference.NEAREST)
479 && ((this._state.master != null && this._state.master.isConnected())
480 || (this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0))) {
4810 isConnected = true;
4820 } else if(read == ReadPreference.SECONDARY) {
4830 isConnected = this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0;
484 }
485
486 // No valid connection return false
4870 return isConnected;
488}
489
4901ReplSet.prototype.isMongos = function() {
4910 return false;
492}
493
4941ReplSet.prototype.checkoutWriter = function() {
4950 if(this._state.master) return this._state.master.checkoutWriter();
4960 return new Error("no writer connection available");
497}
498
4991ReplSet.prototype.processIsMaster = function(_server, _ismaster) {
500 // Server in recovery mode, remove it from available servers
5010 if(!_ismaster.ismaster && !_ismaster.secondary) {
502 // Locate the actual server
5030 var server = this._state.addresses[_server.name];
504 // Close the server, simulating the closing of the connection
505 // to get right removal semantics
5060 if(server) server.close();
507 // Execute any callback errors
5080 _handler(null, this, server)(new Error("server is in recovery mode"));
509 }
510}
511
5121ReplSet.prototype.allRawConnections = function() {
5130 var connections = [];
514
5150 for(var name in this._state.addresses) {
5160 connections = connections.concat(this._state.addresses[name].allRawConnections());
517 }
518
5190 return connections;
520}
521
522/**
523 * @ignore
524 */
5251ReplSet.prototype.allServerInstances = function() {
5260 var self = this;
527 // If no state yet return empty
5280 if(!self._state) return [];
529 // Close all the servers (concatenate entire list of servers first for ease)
5300 var allServers = self._state.master != null ? [self._state.master] : [];
531
532 // Secondary keys
5330 var keys = Object.keys(self._state.secondaries);
534 // Add all secondaries
5350 for(var i = 0; i < keys.length; i++) {
5360 allServers.push(self._state.secondaries[keys[i]]);
537 }
538
539 // Return complete list of all servers
5400 return allServers;
541}
542
543/**
544 * @ignore
545 */
5461ReplSet.prototype.checkoutReader = function(readPreference, tags) {
5470 var connection = null;
548
549 // If we have a read preference object unpack it
5500 if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') {
551 // Validate if the object is using a valid mode
5520 if(!readPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + readPreference.mode);
553 // Set the tag
5540 tags = readPreference.tags;
5550 readPreference = readPreference.mode;
5560 } else if(typeof readPreference == 'object' && readPreference['_type'] != 'ReadPreference') {
5570 return new Error("read preferences must be either a string or an instance of ReadPreference");
558 }
559
560 // Set up our read Preference, allowing us to override the readPreference
5610 var finalReadPreference = readPreference != null ? readPreference : this.options.readPreference;
562
563 // Ensure we unpack a reference
5640 if(finalReadPreference != null && typeof finalReadPreference == 'object' && finalReadPreference['_type'] == 'ReadPreference') {
565 // Validate if the object is using a valid mode
5660 if(!finalReadPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + finalReadPreference.mode);
567 // Set the tag
5680 tags = finalReadPreference.tags;
5690 readPreference = finalReadPreference.mode;
570 }
571
572 // Finalize the read preference setup
5730 finalReadPreference = finalReadPreference == true ? ReadPreference.SECONDARY_PREFERRED : finalReadPreference;
5740 finalReadPreference = finalReadPreference == null ? ReadPreference.PRIMARY : finalReadPreference;
575
576 // If we are reading from a primary
5770 if(finalReadPreference == 'primary') {
578 // If we provide a tags set send an error
5790 if(typeof tags == 'object' && tags != null) {
5800 return new Error("PRIMARY cannot be combined with tags");
581 }
582
583 // If we provide a tags set send an error
5840 if(this._state.master == null) {
5850 return new Error("No replica set primary available for query with ReadPreference PRIMARY");
586 }
587
588 // Checkout a writer
5890 return this.checkoutWriter();
590 }
591
592 // If we have specified to read from a secondary server grab a random one and read
593 // from it, otherwise just pass the primary connection
5940 if((this.options.readSecondary || finalReadPreference == ReadPreference.SECONDARY_PREFERRED || finalReadPreference == ReadPreference.SECONDARY) && Object.keys(this._state.secondaries).length > 0) {
595 // If we have tags, look for servers matching the specific tag
5960 if(this.strategyInstance != null) {
597 // Only pick from secondaries
5980 var _secondaries = [];
5990 for(var key in this._state.secondaries) {
6000 _secondaries.push(this._state.secondaries[key]);
601 }
602
6030 if(finalReadPreference == ReadPreference.SECONDARY) {
604 // Check out the nearest from only the secondaries
6050 connection = this.strategyInstance.checkoutConnection(tags, _secondaries);
606 } else {
6070 connection = this.strategyInstance.checkoutConnection(tags, _secondaries);
608 // No candidate servers that match the tags, error
6090 if(connection == null || connection instanceof Error) {
610 // No secondary server avilable, attemp to checkout a primary server
6110 connection = this.checkoutWriter();
612 // If no connection return an error
6130 if(connection == null || connection instanceof Error) {
6140 return new Error("No replica set members available for query");
615 }
616 }
617 }
6180 } else if(tags != null && typeof tags == 'object') {
619 // Get connection
6200 connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) {
621 // No candidate servers that match the tags, error
6220 if(connection == null) {
6230 return new Error("No replica set members available for query");
624 }
625 } else {
6260 connection = _roundRobin(this, tags);
627 }
6280 } else if(finalReadPreference == ReadPreference.PRIMARY_PREFERRED) {
629 // Check if there is a primary available and return that if possible
6300 connection = this.checkoutWriter();
631 // If no connection available checkout a secondary
6320 if(connection == null || connection instanceof Error) {
633 // If we have tags, look for servers matching the specific tag
6340 if(tags != null && typeof tags == 'object') {
635 // Get connection
6360 connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) {
637 // No candidate servers that match the tags, error
6380 if(connection == null) {
6390 return new Error("No replica set members available for query");
640 }
641 } else {
6420 connection = _roundRobin(this, tags);
643 }
644 }
6450 } else if(finalReadPreference == ReadPreference.SECONDARY_PREFERRED) {
646 // If we have tags, look for servers matching the specific tag
6470 if(this.strategyInstance != null) {
6480 connection = this.strategyInstance.checkoutConnection(tags);
649
650 // No candidate servers that match the tags, error
6510 if(connection == null || connection instanceof Error) {
652 // No secondary server avilable, attemp to checkout a primary server
6530 connection = this.checkoutWriter();
654 // If no connection return an error
6550 if(connection == null || connection instanceof Error) {
6560 var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference;
6570 return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
658 }
659 }
6600 } else if(tags != null && typeof tags == 'object') {
661 // Get connection
6620 connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) {
663 // No candidate servers that match the tags, error
6640 if(connection == null) {
665 // No secondary server avilable, attemp to checkout a primary server
6660 connection = this.checkoutWriter();
667 // If no connection return an error
6680 if(connection == null || connection instanceof Error) {
6690 var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference;
6700 return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
671 }
672 }
673 }
6740 } else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance != null) {
6750 connection = this.strategyInstance.checkoutConnection(tags);
6760 } else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance == null) {
6770 return new Error("A strategy for calculating nearness must be enabled such as ping or statistical");
6780 } else if(finalReadPreference == ReadPreference.SECONDARY && Object.keys(this._state.secondaries).length == 0) {
6790 if(tags != null && typeof tags == 'object') {
6800 var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference;
6810 return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
682 } else {
6830 return new Error("No replica set secondary available for query with ReadPreference SECONDARY");
684 }
685 } else {
6860 connection = this.checkoutWriter();
687 }
688
689 // Return the connection
6900 return connection;
691}
692
693/**
694 * @ignore
695 */
6961var _pickFromTags = function(self, tags) {
697 // If we have an array or single tag selection
6980 var tagObjects = Array.isArray(tags) ? tags : [tags];
699 // Iterate over all tags until we find a candidate server
7000 for(var _i = 0; _i < tagObjects.length; _i++) {
701 // Grab a tag object
7020 var tagObject = tagObjects[_i];
703 // Matching keys
7040 var matchingKeys = Object.keys(tagObject);
705 // Match all the servers that match the provdided tags
7060 var keys = Object.keys(self._state.secondaries);
7070 var candidateServers = [];
708
7090 for(var i = 0; i < keys.length; i++) {
7100 var server = self._state.secondaries[keys[i]];
711 // If we have tags match
7120 if(server.tags != null) {
7130 var matching = true;
714 // Ensure we have all the values
7150 for(var j = 0; j < matchingKeys.length; j++) {
7160 if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) {
7170 matching = false;
7180 break;
719 }
720 }
721
722 // If we have a match add it to the list of matching servers
7230 if(matching) {
7240 candidateServers.push(server);
725 }
726 }
727 }
728
729 // If we have a candidate server return
7300 if(candidateServers.length > 0) {
7310 if(self.strategyInstance) return self.strategyInstance.checkoutConnection(tags, candidateServers);
732 // Set instance to return
7330 return candidateServers[Math.floor(Math.random() * candidateServers.length)].checkoutReader();
734 }
735 }
736
737 // No connection found
7380 return null;
739}
740
741/**
742 * Pick a secondary using round robin
743 *
744 * @ignore
745 */
7461function _roundRobin (replset, tags) {
7470 var keys = Object.keys(replset._state.secondaries);
748 // Update index
7490 replset._currentServerChoice = replset._currentServerChoice + 1;
750 // Pick a server
7510 var key = keys[replset._currentServerChoice % keys.length];
752
7530 var conn = null != replset._state.secondaries[key]
754 ? replset._state.secondaries[key].checkoutReader()
755 : null;
756
757 // If connection is null fallback to first available secondary
7580 if(null == conn) {
7590 conn = pickFirstConnectedSecondary(replset, tags);
760 }
761
7620 return conn;
763}
764
765/**
766 * @ignore
767 */
7681var pickFirstConnectedSecondary = function pickFirstConnectedSecondary(self, tags) {
7690 var keys = Object.keys(self._state.secondaries);
7700 var connection;
771
772 // Find first available reader if any
7730 for(var i = 0; i < keys.length; i++) {
7740 connection = self._state.secondaries[keys[i]].checkoutReader();
7750 if(connection) return connection;
776 }
777
778 // If we still have a null, read from primary if it's not secondary only
7790 if(self._readPreference == ReadPreference.SECONDARY_PREFERRED) {
7800 connection = self._state.master.checkoutReader();
7810 if(connection) return connection;
782 }
783
7840 var preferenceName = self._readPreference == ReadPreference.SECONDARY_PREFERRED
785 ? 'secondary'
786 : self._readPreference;
787
7880 return new Error("No replica set member available for query with ReadPreference "
789 + preferenceName + " and tags " + JSON.stringify(tags));
790}
791
792/**
793 * Get list of secondaries
794 * @ignore
795 */
7961Object.defineProperty(ReplSet.prototype, "secondaries", {enumerable: true
797 , get: function() {
7980 return utils.objectToArray(this._state.secondaries);
799 }
800});
801
802/**
803 * Get list of secondaries
804 * @ignore
805 */
8061Object.defineProperty(ReplSet.prototype, "arbiters", {enumerable: true
807 , get: function() {
8080 return utils.objectToArray(this._state.arbiters);
809 }
810});
811
812

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js

17%
46
8
38
LineHitsSource
1/**
2 * Interval state object constructor
3 *
4 * @ignore
5 */
61var ReplSetState = function ReplSetState (replset) {
70 this.errorMessages = [];
80 this.secondaries = {};
90 this.addresses = {};
100 this.arbiters = {};
110 this.passives = {};
120 this.members = [];
130 this.errors = {};
140 this.setName = null;
150 this.master = null;
160 this.replset = replset;
17}
18
191ReplSetState.prototype.hasValidServers = function() {
200 var validServers = [];
210 if(this.master && this.master.isConnected()) return true;
22
230 if(this.secondaries) {
240 var keys = Object.keys(this.secondaries)
250 for(var i = 0; i < keys.length; i++) {
260 if(this.secondaries[keys[i]].isConnected())
270 return true;
28 }
29 }
30
310 return false;
32}
33
341ReplSetState.prototype.getAllReadServers = function() {
350 var candidate_servers = [];
360 for(var name in this.addresses) {
370 candidate_servers.push(this.addresses[name]);
38 }
39
40 // Return all possible read candidates
410 return candidate_servers;
42}
43
441ReplSetState.prototype.addServer = function(server, master) {
450 server.name = master.me;
46
470 if(master.ismaster) {
480 this.master = server;
490 this.addresses[server.name] = server;
500 this.replset.emit('joined', "primary", master, server);
510 } else if(master.secondary) {
520 this.secondaries[server.name] = server;
530 this.addresses[server.name] = server;
540 this.replset.emit('joined', "secondary", master, server);
550 } else if(master.arbiters) {
560 this.arbiters[server.name] = server;
570 this.addresses[server.name] = server;
580 this.replset.emit('joined', "arbiter", master, server);
59 }
60}
61
621ReplSetState.prototype.contains = function(host) {
630 return this.addresses[host] != null;
64}
65
661ReplSetState.prototype.isPrimary = function(server) {
670 return this.master && this.master.name == server.name;
68}
69
701ReplSetState.prototype.isSecondary = function(server) {
710 return this.secondaries[server.name] != null;
72}
73
741exports.ReplSetState = ReplSetState;
75

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js

4%
145
6
139
LineHitsSource
11var Server = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/../../server").Server
2 , format = require('util').format;
3
4// The ping strategy uses pings each server and records the
5// elapsed time for the server so it can pick a server based on lowest
6// return time for the db command {ping:true}
71var PingStrategy = exports.PingStrategy = function(replicaset, secondaryAcceptableLatencyMS) {
80 this.replicaset = replicaset;
90 this.secondaryAcceptableLatencyMS = secondaryAcceptableLatencyMS;
100 this.state = 'disconnected';
110 this.pingInterval = 5000;
12 // Class instance
130 this.Db = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/../../../db").Db;
14 // Active db connections
150 this.dbs = {};
16 // Current server index
170 this.index = 0;
18 // Logger api
190 this.Logger = null;
20}
21
22// Starts any needed code
231PingStrategy.prototype.start = function(callback) {
24 // already running?
250 if ('connected' == this.state) return;
26
270 this.state = 'connected';
28
29 // Start ping server
300 this._pingServer(callback);
31}
32
33// Stops and kills any processes running
341PingStrategy.prototype.stop = function(callback) {
35 // Stop the ping process
360 this.state = 'disconnected';
37
38 // Stop all the server instances
390 for(var key in this.dbs) {
400 this.dbs[key].close();
41 }
42
43 // optional callback
440 callback && callback(null, null);
45}
46
471PingStrategy.prototype.checkoutConnection = function(tags, secondaryCandidates) {
48 // Servers are picked based on the lowest ping time and then servers that lower than that + secondaryAcceptableLatencyMS
49 // Create a list of candidat servers, containing the primary if available
500 var candidateServers = [];
510 var self = this;
52
53 // If we have not provided a list of candidate servers use the default setup
540 if(!Array.isArray(secondaryCandidates)) {
550 candidateServers = this.replicaset._state.master != null ? [this.replicaset._state.master] : [];
56 // Add all the secondaries
570 var keys = Object.keys(this.replicaset._state.secondaries);
580 for(var i = 0; i < keys.length; i++) {
590 candidateServers.push(this.replicaset._state.secondaries[keys[i]])
60 }
61 } else {
620 candidateServers = secondaryCandidates;
63 }
64
65 // Final list of eligable server
660 var finalCandidates = [];
67
68 // If we have tags filter by tags
690 if(tags != null && typeof tags == 'object') {
70 // If we have an array or single tag selection
710 var tagObjects = Array.isArray(tags) ? tags : [tags];
72 // Iterate over all tags until we find a candidate server
730 for(var _i = 0; _i < tagObjects.length; _i++) {
74 // Grab a tag object
750 var tagObject = tagObjects[_i];
76 // Matching keys
770 var matchingKeys = Object.keys(tagObject);
78 // Remove any that are not tagged correctly
790 for(var i = 0; i < candidateServers.length; i++) {
800 var server = candidateServers[i];
81 // If we have tags match
820 if(server.tags != null) {
830 var matching = true;
84
85 // Ensure we have all the values
860 for(var j = 0; j < matchingKeys.length; j++) {
870 if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) {
880 matching = false;
890 break;
90 }
91 }
92
93 // If we have a match add it to the list of matching servers
940 if(matching) {
950 finalCandidates.push(server);
96 }
97 }
98 }
99 }
100 } else {
101 // Final array candidates
1020 var finalCandidates = candidateServers;
103 }
104
105 // Sort by ping time
1060 finalCandidates.sort(function(a, b) {
1070 return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs'];
108 });
109
1100 if(0 === finalCandidates.length)
1110 return new Error("No replica set members available for query");
112
113 // find lowest server with a ping time
1140 var lowest = finalCandidates.filter(function (server) {
1150 return undefined != server.runtimeStats.pingMs;
116 })[0];
117
1180 if(!lowest) {
1190 lowest = finalCandidates[0];
120 }
121
122 // convert to integer
1230 var lowestPing = lowest.runtimeStats.pingMs | 0;
124
125 // determine acceptable latency
1260 var acceptable = lowestPing + this.secondaryAcceptableLatencyMS;
127
128 // remove any server responding slower than acceptable
1290 var len = finalCandidates.length;
1300 while(len--) {
1310 if(finalCandidates[len].runtimeStats['pingMs'] > acceptable) {
1320 finalCandidates.splice(len, 1);
133 }
134 }
135
1360 if(self.logger && self.logger.debug) {
1370 self.logger.debug("Ping strategy selection order for tags", tags);
1380 finalCandidates.forEach(function(c) {
1390 self.logger.debug(format("%s:%s = %s ms", c.host, c.port, c.runtimeStats['pingMs']), null);
140 })
141 }
142
143 // If no candidates available return an error
1440 if(finalCandidates.length == 0)
1450 return new Error("No replica set members available for query");
146
147 // Ensure no we don't overflow
1480 this.index = this.index % finalCandidates.length
149 // Pick a random acceptable server
1500 var connection = finalCandidates[this.index].checkoutReader();
151 // Point to next candidate (round robin style)
1520 this.index = this.index + 1;
153
1540 if(self.logger && self.logger.debug) {
1550 if(connection)
1560 self.logger.debug("picked server %s:%s", connection.socketOptions.host, connection.socketOptions.port);
157 }
158
1590 return connection;
160}
161
1621PingStrategy.prototype._pingServer = function(callback) {
1630 var self = this;
164
165 // Ping server function
1660 var pingFunction = function() {
167 // Our state changed to disconnected or destroyed return
1680 if(self.state == 'disconnected' || self.state == 'destroyed') return;
169 // If the replicaset is destroyed return
1700 if(self.replicaset.isDestroyed() || self.replicaset._serverState == 'disconnected') return
171
172 // Create a list of all servers we can send the ismaster command to
1730 var allServers = self.replicaset._state.master != null ? [self.replicaset._state.master] : [];
174
175 // Secondary keys
1760 var keys = Object.keys(self.replicaset._state.secondaries);
177 // Add all secondaries
1780 for(var i = 0; i < keys.length; i++) {
1790 allServers.push(self.replicaset._state.secondaries[keys[i]]);
180 }
181
182 // Number of server entries
1830 var numberOfEntries = allServers.length;
184
185 // We got keys
1860 for(var i = 0; i < allServers.length; i++) {
187
188 // We got a server instance
1890 var server = allServers[i];
190
191 // Create a new server object, avoid using internal connections as they might
192 // be in an illegal state
1930 new function(serverInstance) {
1940 var _db = self.dbs[serverInstance.host + ":" + serverInstance.port];
195 // If we have a db
1960 if(_db != null) {
197 // Startup time of the command
1980 var startTime = Date.now();
199
200 // Execute ping command in own scope
2010 var _ping = function(__db, __serverInstance) {
202 // Execute ping on this connection
2030 __db.executeDbCommand({ping:1}, {failFast:true}, function(err) {
2040 if(err) {
2050 delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port];
2060 __db.close();
2070 return done();
208 }
209
2100 if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) {
2110 __serverInstance.runtimeStats['pingMs'] = Date.now() - startTime;
212 }
213
2140 __db.executeDbCommand({ismaster:1}, {failFast:true}, function(err, result) {
2150 if(err) {
2160 delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port];
2170 __db.close();
2180 return done();
219 }
220
221 // Process the ismaster for the server
2220 if(result && result.documents && self.replicaset.processIsMaster) {
2230 self.replicaset.processIsMaster(__serverInstance, result.documents[0]);
224 }
225
226 // Done with the pinging
2270 done();
228 });
229 });
230 };
231 // Ping
2320 _ping(_db, serverInstance);
233 } else {
2340 var connectTimeoutMS = self.replicaset.options.socketOptions
235 ? self.replicaset.options.socketOptions.connectTimeoutMS : 0
236
237 // Create a new master connection
2380 var _server = new Server(serverInstance.host, serverInstance.port, {
239 auto_reconnect: false,
240 returnIsMasterResults: true,
241 slaveOk: true,
242 poolSize: 1,
243 socketOptions: { connectTimeoutMS: connectTimeoutMS },
244 ssl: self.replicaset.options.ssl,
245 sslValidate: self.replicaset.options.sslValidate,
246 sslCA: self.replicaset.options.sslCA,
247 sslCert: self.replicaset.options.sslCert,
248 sslKey: self.replicaset.options.sslKey,
249 sslPass: self.replicaset.options.sslPass
250 });
251
252 // Create Db instance
2530 var _db = new self.Db('local', _server, { safe: true });
2540 _db.on("close", function() {
2550 delete self.dbs[this.serverConfig.host + ":" + this.serverConfig.port];
256 })
257
2580 var _ping = function(__db, __serverInstance) {
2590 if(self.state == 'disconnected') {
2600 self.stop();
2610 return;
262 }
263
2640 __db.open(function(err, db) {
2650 if(self.state == 'disconnected' && __db != null) {
2660 return __db.close();
267 }
268
2690 if(err) {
2700 delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port];
2710 __db.close();
2720 return done();
273 }
274
275 // Save instance
2760 self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port] = __db;
277
278 // Startup time of the command
2790 var startTime = Date.now();
280
281 // Execute ping on this connection
2820 __db.executeDbCommand({ping:1}, {failFast:true}, function(err) {
2830 if(err) {
2840 delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port];
2850 __db.close();
2860 return done();
287 }
288
2890 if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) {
2900 __serverInstance.runtimeStats['pingMs'] = Date.now() - startTime;
291 }
292
2930 __db.executeDbCommand({ismaster:1}, {failFast:true}, function(err, result) {
2940 if(err) {
2950 delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port];
2960 __db.close();
2970 return done();
298 }
299
300 // Process the ismaster for the server
3010 if(result && result.documents && self.replicaset.processIsMaster) {
3020 self.replicaset.processIsMaster(__serverInstance, result.documents[0]);
303 }
304
305 // Done with the pinging
3060 done();
307 });
308 });
309 });
310 };
311
312 // Ping the server
3130 _ping(_db, serverInstance);
314 }
315
3160 function done() {
317 // Adjust the number of checks
3180 numberOfEntries--;
319
320 // If we are done with all results coming back trigger ping again
3210 if(0 === numberOfEntries && 'connected' == self.state) {
3220 setTimeout(pingFunction, self.pingInterval);
323 }
324 }
325 }(server);
326 }
327 }
328
329 // Start pingFunction
3300 pingFunction();
331
3320 callback && callback(null);
333}
334

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js

11%
34
4
30
LineHitsSource
1// The Statistics strategy uses the measure of each end-start time for each
2// query executed against the db to calculate the mean, variance and standard deviation
3// and pick the server which the lowest mean and deviation
41var StatisticsStrategy = exports.StatisticsStrategy = function(replicaset) {
50 this.replicaset = replicaset;
6 // Logger api
70 this.Logger = null;
8}
9
10// Starts any needed code
111StatisticsStrategy.prototype.start = function(callback) {
120 callback && callback(null, null);
13}
14
151StatisticsStrategy.prototype.stop = function(callback) {
160 callback && callback(null, null);
17}
18
191StatisticsStrategy.prototype.checkoutConnection = function(tags, secondaryCandidates) {
20 // Servers are picked based on the lowest ping time and then servers that lower than that + secondaryAcceptableLatencyMS
21 // Create a list of candidat servers, containing the primary if available
220 var candidateServers = [];
23
24 // If we have not provided a list of candidate servers use the default setup
250 if(!Array.isArray(secondaryCandidates)) {
260 candidateServers = this.replicaset._state.master != null ? [this.replicaset._state.master] : [];
27 // Add all the secondaries
280 var keys = Object.keys(this.replicaset._state.secondaries);
290 for(var i = 0; i < keys.length; i++) {
300 candidateServers.push(this.replicaset._state.secondaries[keys[i]])
31 }
32 } else {
330 candidateServers = secondaryCandidates;
34 }
35
36 // Final list of eligable server
370 var finalCandidates = [];
38
39 // If we have tags filter by tags
400 if(tags != null && typeof tags == 'object') {
41 // If we have an array or single tag selection
420 var tagObjects = Array.isArray(tags) ? tags : [tags];
43 // Iterate over all tags until we find a candidate server
440 for(var _i = 0; _i < tagObjects.length; _i++) {
45 // Grab a tag object
460 var tagObject = tagObjects[_i];
47 // Matching keys
480 var matchingKeys = Object.keys(tagObject);
49 // Remove any that are not tagged correctly
500 for(var i = 0; i < candidateServers.length; i++) {
510 var server = candidateServers[i];
52 // If we have tags match
530 if(server.tags != null) {
540 var matching = true;
55
56 // Ensure we have all the values
570 for(var j = 0; j < matchingKeys.length; j++) {
580 if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) {
590 matching = false;
600 break;
61 }
62 }
63
64 // If we have a match add it to the list of matching servers
650 if(matching) {
660 finalCandidates.push(server);
67 }
68 }
69 }
70 }
71 } else {
72 // Final array candidates
730 var finalCandidates = candidateServers;
74 }
75
76 // If no candidates available return an error
770 if(finalCandidates.length == 0) return new Error("No replica set members available for query");
78 // Pick a random server
790 return finalCandidates[Math.round(Math.random(1000000) * (finalCandidates.length - 1))].checkoutReader();
80}
81

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/server.js

9%
378
37
341
LineHitsSource
11var Connection = require('./connection').Connection,
2 ReadPreference = require('./read_preference').ReadPreference,
3 DbCommand = require('../commands/db_command').DbCommand,
4 MongoReply = require('../responses/mongo_reply').MongoReply,
5 ConnectionPool = require('./connection_pool').ConnectionPool,
6 EventEmitter = require('events').EventEmitter,
7 ServerCapabilities = require('./server_capabilities').ServerCapabilities,
8 Base = require('./base').Base,
9 format = require('util').format,
10 utils = require('../utils'),
11 timers = require('timers'),
12 inherits = require('util').inherits;
13
14// Set processor, setImmediate if 0.10 otherwise nextTick
151var processor = require('../utils').processor();
16
17/**
18 * Class representing a single MongoDB Server connection
19 *
20 * Options
21 * - **readPreference** {String, default:null}, set's the read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST)
22 * - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support)
23 * - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
24 * - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
25 * - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
26 * - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
27 * - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher)
28 * - **poolSize** {Number, default:5}, number of connections in the connection pool, set to 5 as default for legacy reasons.
29 * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number))
30 * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**.
31 * - **auto_reconnect** {Boolean, default:false}, reconnect on error.
32 * - **disableDriverBSONSizeCheck** {Boolean, default:false}, force the server to error if the BSON message is to big
33 *
34 * @class Represents a Server connection.
35 * @param {String} host the server host
36 * @param {Number} port the server port
37 * @param {Object} [options] optional options for insert command
38 */
391function Server(host, port, options) {
40 // Set up Server instance
410 if(!(this instanceof Server)) return new Server(host, port, options);
42
43 // Set up event emitter
440 Base.call(this);
45
46 // Ensure correct values
470 if(port != null && typeof port == 'object') {
480 options = port;
490 port = Connection.DEFAULT_PORT;
50 }
51
520 var self = this;
530 this.host = host;
540 this.port = port;
550 this.options = options == null ? {} : options;
560 this.internalConnection;
570 this.internalMaster = false;
580 this.connected = false;
590 this.poolSize = this.options.poolSize == null ? 5 : this.options.poolSize;
600 this.disableDriverBSONSizeCheck = this.options.disableDriverBSONSizeCheck != null ? this.options.disableDriverBSONSizeCheck : false;
610 this._used = false;
620 this.replicasetInstance = null;
63
64 // Emit open setup
650 this.emitOpen = this.options.emitOpen || true;
66 // Set ssl as connection method
670 this.ssl = this.options.ssl == null ? false : this.options.ssl;
68 // Set ssl validation
690 this.sslValidate = this.options.sslValidate == null ? false : this.options.sslValidate;
70 // Set the ssl certificate authority (array of Buffer/String keys)
710 this.sslCA = Array.isArray(this.options.sslCA) ? this.options.sslCA : null;
72 // Certificate to present to the server
730 this.sslCert = this.options.sslCert;
74 // Certificate private key if in separate file
750 this.sslKey = this.options.sslKey;
76 // Password to unlock private key
770 this.sslPass = this.options.sslPass;
78 // Server capabilities
790 this.serverCapabilities = null;
80 // Set server name
810 this.name = format("%s:%s", host, port);
82
83 // Ensure we are not trying to validate with no list of certificates
840 if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) {
850 throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate");
86 }
87
88 // Get the readPreference
890 var readPreference = this.options['readPreference'];
90 // If readPreference is an object get the mode string
910 var validateReadPreference = readPreference != null && typeof readPreference == 'object' ? readPreference.mode : readPreference;
92 // Read preference setting
930 if(validateReadPreference != null) {
940 if(validateReadPreference != ReadPreference.PRIMARY && validateReadPreference != ReadPreference.SECONDARY && validateReadPreference != ReadPreference.NEAREST
95 && validateReadPreference != ReadPreference.SECONDARY_PREFERRED && validateReadPreference != ReadPreference.PRIMARY_PREFERRED) {
960 throw new Error("Illegal readPreference mode specified, " + validateReadPreference);
97 }
98
99 // Set read Preference
1000 this._readPreference = readPreference;
101 } else {
1020 this._readPreference = null;
103 }
104
105 // Contains the isMaster information returned from the server
1060 this.isMasterDoc;
107
108 // Set default connection pool options
1090 this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {};
1100 if(this.disableDriverBSONSizeCheck) this.socketOptions.disableDriverBSONSizeCheck = this.disableDriverBSONSizeCheck;
111
112 // Set ssl up if it's defined
1130 if(this.ssl) {
1140 this.socketOptions.ssl = true;
115 // Set ssl validation
1160 this.socketOptions.sslValidate = this.sslValidate == null ? false : this.sslValidate;
117 // Set the ssl certificate authority (array of Buffer/String keys)
1180 this.socketOptions.sslCA = Array.isArray(this.sslCA) ? this.sslCA : null;
119 // Set certificate to present
1200 this.socketOptions.sslCert = this.sslCert;
121 // Set certificate to present
1220 this.socketOptions.sslKey = this.sslKey;
123 // Password to unlock private key
1240 this.socketOptions.sslPass = this.sslPass;
125 }
126
127 // Set up logger if any set
1280 this.logger = this.options.logger != null
129 && (typeof this.options.logger.debug == 'function')
130 && (typeof this.options.logger.error == 'function')
131 && (typeof this.options.logger.log == 'function')
132 ? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}};
133
134 // Just keeps list of events we allow
1350 this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[]};
136 // Internal state of server connection
1370 this._serverState = 'disconnected';
138 // Contains state information about server connection
1390 this._state = {'runtimeStats': {'queryStats':new RunningStats()}};
140 // Do we record server stats or not
1410 this.recordQueryStats = false;
142
143 // Allow setting the socketTimeoutMS on all connections
144 // to work around issues such as secondaries blocking due to compaction
1450 utils.setSocketTimeoutProperty(this, this.socketOptions);
146};
147
148/**
149 * @ignore
150 */
1511inherits(Server, Base);
152
153//
154// Deprecated, USE ReadPreferences class
155//
1561Server.READ_PRIMARY = ReadPreference.PRIMARY;
1571Server.READ_SECONDARY = ReadPreference.SECONDARY_PREFERRED;
1581Server.READ_SECONDARY_ONLY = ReadPreference.SECONDARY;
159
160/**
161 * Always ourselves
162 * @ignore
163 */
1641Server.prototype.setReadPreference = function(readPreference) {
1650 this._readPreference = readPreference;
166}
167
168/**
169 * @ignore
170 */
1711Server.prototype.isMongos = function() {
1720 return this.isMasterDoc != null && this.isMasterDoc['msg'] == "isdbgrid" ? true : false;
173}
174
175/**
176 * @ignore
177 */
1781Server.prototype._isUsed = function() {
1790 return this._used;
180}
181
182/**
183 * @ignore
184 */
1851Server.prototype.close = function(callback) {
186 // Set server status as disconnected
1870 this._serverState = 'destroyed';
188 // Remove all local listeners
1890 this.removeAllListeners();
190
1910 if(this.connectionPool != null) {
192 // Remove all the listeners on the pool so it does not fire messages all over the place
1930 this.connectionPool.removeAllEventListeners();
194 // Close the connection if it's open
1950 this.connectionPool.stop(true);
196 }
197
198 // Emit close event
1990 if(this.db && !this.isSetMember()) {
2000 var self = this;
2010 processor(function() {
2020 self._emitAcrossAllDbInstances(self, null, "close", null, null, true)
203 })
204
205 // Flush out any remaining call handlers
2060 self._flushAllCallHandlers(utils.toError("Connection Closed By Application"));
207 }
208
209 // Peform callback if present
2100 if(typeof callback === 'function') callback(null);
211};
212
2131Server.prototype.isDestroyed = function() {
2140 return this._serverState == 'destroyed';
215}
216
217/**
218 * @ignore
219 */
2201Server.prototype.isConnected = function() {
2210 return this.connectionPool != null && this.connectionPool.isConnected();
222}
223
224/**
225 * @ignore
226 */
2271Server.prototype.canWrite = Server.prototype.isConnected;
2281Server.prototype.canRead = Server.prototype.isConnected;
229
2301Server.prototype.isAutoReconnect = function() {
2310 if(this.isSetMember()) return false;
2320 return this.options.auto_reconnect != null ? this.options.auto_reconnect : true;
233}
234
235/**
236 * @ignore
237 */
2381Server.prototype.allServerInstances = function() {
2390 return [this];
240}
241
242/**
243 * @ignore
244 */
2451Server.prototype.isSetMember = function() {
2460 return this.replicasetInstance != null || this.mongosInstance != null;
247}
248
249/**
250 * Assigns a replica set to this `server`.
251 *
252 * @param {ReplSet} replset
253 * @ignore
254 */
2551Server.prototype.assignReplicaSet = function (replset) {
2560 this.replicasetInstance = replset;
2570 this.inheritReplSetOptionsFrom(replset);
2580 this.enableRecordQueryStats(replset.recordQueryStats);
259}
260
261/**
262 * Takes needed options from `replset` and overwrites
263 * our own options.
264 *
265 * @param {ReplSet} replset
266 * @ignore
267 */
2681Server.prototype.inheritReplSetOptionsFrom = function (replset) {
2690 this.socketOptions = {};
2700 this.socketOptions.connectTimeoutMS = replset.options.socketOptions.connectTimeoutMS || 30000;
271
2720 if(replset.options.ssl) {
273 // Set ssl on
2740 this.socketOptions.ssl = true;
275 // Set ssl validation
2760 this.socketOptions.sslValidate = replset.options.sslValidate == null ? false : replset.options.sslValidate;
277 // Set the ssl certificate authority (array of Buffer/String keys)
2780 this.socketOptions.sslCA = Array.isArray(replset.options.sslCA) ? replset.options.sslCA : null;
279 // Set certificate to present
2800 this.socketOptions.sslCert = replset.options.sslCert;
281 // Set certificate to present
2820 this.socketOptions.sslKey = replset.options.sslKey;
283 // Password to unlock private key
2840 this.socketOptions.sslPass = replset.options.sslPass;
285 }
286
287 // If a socket option object exists clone it
2880 if(utils.isObject(replset.options.socketOptions)) {
2890 var keys = Object.keys(replset.options.socketOptions);
2900 for(var i = 0; i < keys.length; i++)
2910 this.socketOptions[keys[i]] = replset.options.socketOptions[keys[i]];
292 }
293}
294
295/**
296 * Opens this server connection.
297 *
298 * @ignore
299 */
3001Server.prototype.connect = function(dbInstance, options, callback) {
3010 if('function' === typeof options) callback = options, options = {};
3020 if(options == null) options = {};
3030 if(!('function' === typeof callback)) callback = null;
3040 var self = this;
305 // Save the options
3060 this.options = options;
307
308 // Currently needed to work around problems with multiple connections in a pool with ssl
309 // TODO fix if possible
3100 if(this.ssl == true) {
311 // Set up socket options for ssl
3120 this.socketOptions.ssl = true;
313 // Set ssl validation
3140 this.socketOptions.sslValidate = this.sslValidate == null ? false : this.sslValidate;
315 // Set the ssl certificate authority (array of Buffer/String keys)
3160 this.socketOptions.sslCA = Array.isArray(this.sslCA) ? this.sslCA : null;
317 // Set certificate to present
3180 this.socketOptions.sslCert = this.sslCert;
319 // Set certificate to present
3200 this.socketOptions.sslKey = this.sslKey;
321 // Password to unlock private key
3220 this.socketOptions.sslPass = this.sslPass;
323 }
324
325 // Let's connect
3260 var server = this;
327 // Let's us override the main receiver of events
3280 var eventReceiver = options.eventReceiver != null ? options.eventReceiver : this;
329 // Save reference to dbInstance
3300 this.db = dbInstance; // `db` property matches ReplSet and Mongos
3310 this.dbInstances = [dbInstance];
332
333 // Force connection pool if there is one
3340 if(server.connectionPool) server.connectionPool.stop();
335 // Set server state to connecting
3360 this._serverState = 'connecting';
337
3380 if(server.connectionPool != null) {
339 // Remove all the listeners on the pool so it does not fire messages all over the place
3400 this.connectionPool.removeAllEventListeners();
341 // Close the connection if it's open
3420 this.connectionPool.stop(true);
343 }
344
3450 this.connectionPool = new ConnectionPool(this.host, this.port, this.poolSize, dbInstance.bson, this.socketOptions);
3460 var connectionPool = this.connectionPool;
347 // If ssl is not enabled don't wait between the pool connections
3480 if(this.ssl == null || !this.ssl) connectionPool._timeToWait = null;
349 // Set logger on pool
3500 connectionPool.logger = this.logger;
3510 connectionPool.bson = dbInstance.bson;
352
353 // Set basic parameters passed in
3540 var returnIsMasterResults = options.returnIsMasterResults == null ? false : options.returnIsMasterResults;
355
356 // Create a default connect handler, overriden when using replicasets
3570 var connectCallback = function(_server) {
3580 return function(err, reply) {
359 // ensure no callbacks get called twice
3600 var internalCallback = callback;
3610 callback = null;
362
363 // Assign the server
3640 _server = _server != null ? _server : server;
365
366 // If something close down the connection and removed the callback before
367 // proxy killed connection etc, ignore the erorr as close event was isssued
3680 if(err != null && internalCallback == null) return;
369 // Internal callback
3700 if(err != null) return internalCallback(err, null, _server);
3710 _server.master = reply.documents[0].ismaster == 1 ? true : false;
3720 _server.connectionPool.setMaxBsonSize(reply.documents[0].maxBsonObjectSize);
3730 _server.connectionPool.setMaxMessageSizeBytes(reply.documents[0].maxMessageSizeBytes);
374 // Set server state to connEcted
3750 _server._serverState = 'connected';
376 // Set server as connected
3770 _server.connected = true;
378 // Save document returned so we can query it
3790 _server.isMasterDoc = reply.documents[0];
380
3810 if(self.emitOpen) {
3820 _server._emitAcrossAllDbInstances(_server, eventReceiver, "open", null, returnIsMasterResults ? reply : null, null);
3830 self.emitOpen = false;
384 } else {
3850 _server._emitAcrossAllDbInstances(_server, eventReceiver, "reconnect", null, returnIsMasterResults ? reply : null, null);
386 }
387
388 // Set server capabilities
3890 server.serverCapabilities = new ServerCapabilities(_server.isMasterDoc);
390
391 // If we have it set to returnIsMasterResults
3920 if(returnIsMasterResults) {
3930 internalCallback(null, reply, _server);
394 } else {
3950 internalCallback(null, dbInstance, _server);
396 }
397 }
398 };
399
400 // Let's us override the main connect callback
4010 var connectHandler = options.connectHandler == null ? connectCallback(server) : options.connectHandler;
402
403 // Set up on connect method
4040 connectionPool.on("poolReady", function() {
405 // Create db command and Add the callback to the list of callbacks by the request id (mapping outgoing messages to correct callbacks)
4060 var db_command = DbCommand.NcreateIsMasterCommand(dbInstance, dbInstance.databaseName);
407 // Check out a reader from the pool
4080 var connection = connectionPool.checkoutConnection();
409 // Register handler for messages
4100 server._registerHandler(db_command, false, connection, connectHandler);
411 // Write the command out
4120 connection.write(db_command);
413 })
414
415 // Set up item connection
4160 connectionPool.on("message", function(message) {
417 // Attempt to parse the message
4180 try {
419 // Create a new mongo reply
4200 var mongoReply = new MongoReply()
421 // Parse the header
4220 mongoReply.parseHeader(message, connectionPool.bson)
423
424 // If message size is not the same as the buffer size
425 // something went terribly wrong somewhere
4260 if(mongoReply.messageLength != message.length) {
427 // Emit the error
4280 if(eventReceiver.listeners("error") && eventReceiver.listeners("error").length > 0) eventReceiver.emit("error", new Error("bson length is different from message length"), server);
429 // Remove all listeners
4300 server.removeAllListeners();
431 } else {
4320 var startDate = new Date().getTime();
433
434 // Callback instance
4350 var callbackInfo = server._findHandler(mongoReply.responseTo.toString());
436
437 // The command executed another request, log the handler again under that request id
4380 if(mongoReply.requestId > 0 && mongoReply.cursorId.toString() != "0"
439 && callbackInfo && callbackInfo.info && callbackInfo.info.exhaust) {
4400 server._reRegisterHandler(mongoReply.requestId, callbackInfo);
441 }
442 // Parse the body
4430 mongoReply.parseBody(message, connectionPool.bson, callbackInfo.info.raw, function(err) {
4440 if(err != null) {
445 // If pool connection is already closed
4460 if(server._serverState === 'disconnected') return;
447 // Set server state to disconnected
4480 server._serverState = 'disconnected';
449 // Remove all listeners and close the connection pool
4500 server.removeAllListeners();
4510 connectionPool.stop(true);
452
453 // If we have a callback return the error
4540 if(typeof callback === 'function') {
455 // ensure no callbacks get called twice
4560 var internalCallback = callback;
4570 callback = null;
458 // Perform callback
4590 internalCallback(err, null, server);
4600 } else if(server.isSetMember()) {
4610 if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", utils.toError(err), server);
462 } else {
4630 if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", utils.toError(err), server);
464 }
465
466 // If we are a single server connection fire errors correctly
4670 if(!server.isSetMember()) {
468 // Fire all callback errors
4690 server.__executeAllCallbacksWithError(err);
470 // Emit error
4710 server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true);
472 }
473 // Short cut
4740 return;
475 }
476
477 // Let's record the stats info if it's enabled
4780 if(server.recordQueryStats == true && server._state['runtimeStats'] != null
479 && server._state.runtimeStats['queryStats'] instanceof RunningStats) {
480 // Add data point to the running statistics object
4810 server._state.runtimeStats.queryStats.push(new Date().getTime() - callbackInfo.info.start);
482 }
483
484 // Dispatch the call
4850 server._callHandler(mongoReply.responseTo, mongoReply, null);
486
487 // If we have an error about the server not being master or primary
4880 if((mongoReply.responseFlag & (1 << 1)) != 0
489 && mongoReply.documents[0].code
490 && mongoReply.documents[0].code == 13436) {
4910 server.close();
492 }
493 });
494 }
495 } catch (err) {
496 // Throw error in next tick
4970 processor(function() {
4980 throw err;
499 })
500 }
501 });
502
503 // Handle timeout
5040 connectionPool.on("timeout", function(err) {
505 // If pool connection is already closed
5060 if(server._serverState === 'disconnected'
5070 || server._serverState === 'destroyed') return;
508 // Set server state to disconnected
5090 server._serverState = 'disconnected';
510 // If we have a callback return the error
5110 if(typeof callback === 'function') {
512 // ensure no callbacks get called twice
5130 var internalCallback = callback;
5140 callback = null;
515 // Perform callback
5160 internalCallback(err, null, server);
5170 } else if(server.isSetMember()) {
5180 if(server.listeners("timeout") && server.listeners("timeout").length > 0) server.emit("timeout", err, server);
519 } else {
5200 if(eventReceiver.listeners("timeout") && eventReceiver.listeners("timeout").length > 0) eventReceiver.emit("timeout", err, server);
521 }
522
523 // If we are a single server connection fire errors correctly
5240 if(!server.isSetMember()) {
525 // Fire all callback errors
5260 server.__executeAllCallbacksWithError(err);
527 // Emit error
5280 server._emitAcrossAllDbInstances(server, eventReceiver, "timeout", err, server, true);
529 }
530
531 // If we have autoConnect enabled let's fire up an attempt to reconnect
5320 if(server.isAutoReconnect()
533 && !server.isSetMember()
534 && (server._serverState != 'destroyed')
535 && !server._reconnectInProgreess) {
536 // Set the number of retries
5370 server._reconnect_retries = server.db.numberOfRetries;
538 // Attempt reconnect
5390 server._reconnectInProgreess = true;
5400 setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds);
541 }
542 });
543
544 // Handle errors
5450 connectionPool.on("error", function(message, connection, error_options) {
546 // If pool connection is already closed
5470 if(server._serverState === 'disconnected'
5480 || server._serverState === 'destroyed') return;
549
550 // Set server state to disconnected
5510 server._serverState = 'disconnected';
552 // Error message
5530 var error_message = new Error(message && message.err ? message.err : message);
554 // Error message coming from ssl
5550 if(error_options && error_options.ssl) error_message.ssl = true;
556
557 // If we have a callback return the error
5580 if(typeof callback === 'function') {
559 // ensure no callbacks get called twice
5600 var internalCallback = callback;
5610 callback = null;
562 // Perform callback
5630 internalCallback(error_message, null, server);
5640 } else if(server.isSetMember()) {
5650 if(server.listeners("error") && server.listeners("error").length > 0) server.emit("error", error_message, server);
566 } else {
5670 if(eventReceiver.listeners("error") && eventReceiver.listeners("error").length > 0) eventReceiver.emit("error", error_message, server);
568 }
569
570 // If we are a single server connection fire errors correctly
5710 if(!server.isSetMember()) {
572 // Fire all callback errors
5730 server.__executeAllCallbacksWithError(error_message);
574 // Emit error
5750 server._emitAcrossAllDbInstances(server, eventReceiver, "error", error_message, server, true);
576 }
577
578 // If we have autoConnect enabled let's fire up an attempt to reconnect
5790 if(server.isAutoReconnect()
580 && !server.isSetMember()
581 && (server._serverState != 'destroyed')
582 && !server._reconnectInProgreess) {
583
584 // Set the number of retries
5850 server._reconnect_retries = server.db.numberOfRetries;
586 // Attempt reconnect
5870 server._reconnectInProgreess = true;
5880 setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds);
589 }
590 });
591
592 // Handle close events
5930 connectionPool.on("close", function() {
594 // If pool connection is already closed
5950 if(server._serverState === 'disconnected'
5960 || server._serverState === 'destroyed') return;
597 // Set server state to disconnected
5980 server._serverState = 'disconnected';
599 // If we have a callback return the error
6000 if(typeof callback == 'function') {
601 // ensure no callbacks get called twice
6020 var internalCallback = callback;
6030 callback = null;
604 // Perform callback
6050 internalCallback(new Error("connection closed"), null, server);
6060 } else if(server.isSetMember()) {
6070 if(server.listeners("close") && server.listeners("close").length > 0) server.emit("close", new Error("connection closed"), server);
608 } else {
6090 if(eventReceiver.listeners("close") && eventReceiver.listeners("close").length > 0) eventReceiver.emit("close", new Error("connection closed"), server);
610 }
611
612 // If we are a single server connection fire errors correctly
6130 if(!server.isSetMember()) {
614 // Fire all callback errors
6150 server.__executeAllCallbacksWithError(new Error("connection closed"));
616 // Emit error
6170 server._emitAcrossAllDbInstances(server, eventReceiver, "close", server, null, true);
618 }
619
620 // If we have autoConnect enabled let's fire up an attempt to reconnect
6210 if(server.isAutoReconnect()
622 && !server.isSetMember()
623 && (server._serverState != 'destroyed')
624 && !server._reconnectInProgreess) {
625
626 // Set the number of retries
6270 server._reconnect_retries = server.db.numberOfRetries;
628 // Attempt reconnect
6290 server._reconnectInProgreess = true;
6300 setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds);
631 }
632 });
633
634 /**
635 * @ignore
636 */
6370 var __attemptReconnect = function(server) {
6380 return function() {
639 // Attempt reconnect
6400 server.connect(server.db, server.options, function(err, result) {
6410 server._reconnect_retries = server._reconnect_retries - 1;
642
6430 if(err) {
644 // Retry
6450 if(server._reconnect_retries == 0 || server._serverState == 'destroyed') {
6460 server._serverState = 'connected';
6470 server._reconnectInProgreess = false
648 // Fire all callback errors
6490 return server.__executeAllCallbacksWithError(new Error("failed to reconnect to server"));
650 } else {
6510 return setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds);
652 }
653 } else {
654 // Set as authenticating (isConnected will be false)
6550 server._serverState = 'authenticating';
656 // Apply any auths, we don't try to catch any errors here
657 // as there are nowhere to simply propagate them to
6580 self._apply_auths(server.db, function(err, result) {
6590 server._serverState = 'connected';
6600 server._reconnectInProgreess = false;
6610 server._commandsStore.execute_queries();
6620 server._commandsStore.execute_writes();
663 });
664 }
665 });
666 }
667 }
668
669 // If we have a parser error we are in an unknown state, close everything and emit
670 // error
6710 connectionPool.on("parseError", function(err) {
672 // If pool connection is already closed
6730 if(server._serverState === 'disconnected'
6740 || server._serverState === 'destroyed') return;
675 // Set server state to disconnected
6760 server._serverState = 'disconnected';
677 // If we have a callback return the error
6780 if(typeof callback === 'function') {
679 // ensure no callbacks get called twice
6800 var internalCallback = callback;
6810 callback = null;
682 // Perform callback
6830 internalCallback(utils.toError(err), null, server);
6840 } else if(server.isSetMember()) {
6850 if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", utils.toError(err), server);
686 } else {
6870 if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", utils.toError(err), server);
688 }
689
690 // If we are a single server connection fire errors correctly
6910 if(!server.isSetMember()) {
692 // Fire all callback errors
6930 server.__executeAllCallbacksWithError(utils.toError(err));
694 // Emit error
6950 server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true);
696 }
697 });
698
699 // Boot up connection poole, pass in a locator of callbacks
7000 connectionPool.start();
701}
702
703/**
704 * @ignore
705 */
7061Server.prototype.allRawConnections = function() {
7070 return this.connectionPool != null ? this.connectionPool.getAllConnections() : [];
708}
709
710/**
711 * Check if a writer can be provided
712 * @ignore
713 */
7141var canCheckoutWriter = function(self, read) {
715 // We cannot write to an arbiter or secondary server
7160 if(self.isMasterDoc && self.isMasterDoc['arbiterOnly'] == true) {
7170 return new Error("Cannot write to an arbiter");
7180 } if(self.isMasterDoc && self.isMasterDoc['secondary'] == true) {
7190 return new Error("Cannot write to a secondary");
7200 } else if(read == true && self._readPreference == ReadPreference.SECONDARY && self.isMasterDoc && self.isMasterDoc['ismaster'] == true) {
7210 return new Error("Cannot read from primary when secondary only specified");
7220 } else if(!self.isMasterDoc) {
7230 return new Error("Cannot determine state of server");
724 }
725
726 // Return no error
7270 return null;
728}
729
730/**
731 * @ignore
732 */
7331Server.prototype.checkoutWriter = function(read) {
7340 if(read == true) return this.connectionPool.checkoutConnection();
735 // Check if are allowed to do a checkout (if we try to use an arbiter f.ex)
7360 var result = canCheckoutWriter(this, read);
737 // If the result is null check out a writer
7380 if(result == null && this.connectionPool != null) {
7390 var connection = this.connectionPool.checkoutConnection();
740 // Add server capabilities to the connection
7410 if(connection)
7420 connection.serverCapabilities = this.serverCapabilities;
7430 return connection;
7440 } else if(result == null) {
7450 return null;
746 } else {
7470 return result;
748 }
749}
750
751/**
752 * Check if a reader can be provided
753 * @ignore
754 */
7551var canCheckoutReader = function(self) {
756 // We cannot write to an arbiter or secondary server
7570 if(self.isMasterDoc && self.isMasterDoc['arbiterOnly'] == true) {
7580 return new Error("Cannot write to an arbiter");
7590 } else if(self._readPreference != null) {
760 // If the read preference is Primary and the instance is not a master return an error
7610 if((self._readPreference == ReadPreference.PRIMARY) && self.isMasterDoc && self.isMasterDoc['ismaster'] != true) {
7620 return new Error("Read preference is Server.PRIMARY and server is not master");
7630 } else if(self._readPreference == ReadPreference.SECONDARY && self.isMasterDoc && self.isMasterDoc['ismaster'] == true) {
7640 return new Error("Cannot read from primary when secondary only specified");
765 }
7660 } else if(!self.isMasterDoc) {
7670 return new Error("Cannot determine state of server");
768 }
769
770 // Return no error
7710 return null;
772}
773
774/**
775 * @ignore
776 */
7771Server.prototype.checkoutReader = function(read) {
778 // Check if are allowed to do a checkout (if we try to use an arbiter f.ex)
7790 var result = canCheckoutReader(this);
780 // If the result is null check out a writer
7810 if(result == null && this.connectionPool != null) {
7820 var connection = this.connectionPool.checkoutConnection();
783 // Add server capabilities to the connection
7840 if(connection)
7850 connection.serverCapabilities = this.serverCapabilities;
7860 return connection;
7870 } else if(result == null) {
7880 return null;
789 } else {
7900 return result;
791 }
792}
793
794/**
795 * @ignore
796 */
7971Server.prototype.enableRecordQueryStats = function(enable) {
7980 this.recordQueryStats = enable;
799}
800
801/**
802 * Internal statistics object used for calculating average and standard devitation on
803 * running queries
804 * @ignore
805 */
8061var RunningStats = function() {
8070 var self = this;
8080 this.m_n = 0;
8090 this.m_oldM = 0.0;
8100 this.m_oldS = 0.0;
8110 this.m_newM = 0.0;
8120 this.m_newS = 0.0;
813
814 // Define getters
8150 Object.defineProperty(this, "numDataValues", { enumerable: true
8160 , get: function () { return this.m_n; }
817 });
818
8190 Object.defineProperty(this, "mean", { enumerable: true
8200 , get: function () { return (this.m_n > 0) ? this.m_newM : 0.0; }
821 });
822
8230 Object.defineProperty(this, "variance", { enumerable: true
8240 , get: function () { return ((this.m_n > 1) ? this.m_newS/(this.m_n - 1) : 0.0); }
825 });
826
8270 Object.defineProperty(this, "standardDeviation", { enumerable: true
8280 , get: function () { return Math.sqrt(this.variance); }
829 });
830
8310 Object.defineProperty(this, "sScore", { enumerable: true
832 , get: function () {
8330 var bottom = this.mean + this.standardDeviation;
8340 if(bottom == 0) return 0;
8350 return ((2 * this.mean * this.standardDeviation)/(bottom));
836 }
837 });
838}
839
840/**
841 * @ignore
842 */
8431RunningStats.prototype.push = function(x) {
844 // Update the number of samples
8450 this.m_n = this.m_n + 1;
846 // See Knuth TAOCP vol 2, 3rd edition, page 232
8470 if(this.m_n == 1) {
8480 this.m_oldM = this.m_newM = x;
8490 this.m_oldS = 0.0;
850 } else {
8510 this.m_newM = this.m_oldM + (x - this.m_oldM) / this.m_n;
8520 this.m_newS = this.m_oldS + (x - this.m_oldM) * (x - this.m_newM);
853
854 // set up for next iteration
8550 this.m_oldM = this.m_newM;
8560 this.m_oldS = this.m_newS;
857 }
858}
859
860/**
861 * @ignore
862 */
8631Object.defineProperty(Server.prototype, "autoReconnect", { enumerable: true
864 , get: function () {
8650 return this.options['auto_reconnect'] == null ? false : this.options['auto_reconnect'];
866 }
867});
868
869/**
870 * @ignore
871 */
8721Object.defineProperty(Server.prototype, "connection", { enumerable: true
873 , get: function () {
8740 return this.internalConnection;
875 }
876 , set: function(connection) {
8770 this.internalConnection = connection;
878 }
879});
880
881/**
882 * @ignore
883 */
8841Object.defineProperty(Server.prototype, "master", { enumerable: true
885 , get: function () {
8860 return this.internalMaster;
887 }
888 , set: function(value) {
8890 this.internalMaster = value;
890 }
891});
892
893/**
894 * @ignore
895 */
8961Object.defineProperty(Server.prototype, "primary", { enumerable: true
897 , get: function () {
8980 return this;
899 }
900});
901
902/**
903 * Getter for query Stats
904 * @ignore
905 */
9061Object.defineProperty(Server.prototype, "queryStats", { enumerable: true
907 , get: function () {
9080 return this._state.runtimeStats.queryStats;
909 }
910});
911
912/**
913 * @ignore
914 */
9151Object.defineProperty(Server.prototype, "runtimeStats", { enumerable: true
916 , get: function () {
9170 return this._state.runtimeStats;
918 }
919});
920
921/**
922 * Get Read Preference method
923 * @ignore
924 */
9251Object.defineProperty(Server.prototype, "readPreference", { enumerable: true
926 , get: function () {
9270 if(this._readPreference == null && this.readSecondary) {
9280 return Server.READ_SECONDARY;
9290 } else if(this._readPreference == null && !this.readSecondary) {
9300 return Server.READ_PRIMARY;
931 } else {
9320 return this._readPreference;
933 }
934 }
935});
936
937/**
938 * @ignore
939 */
9401exports.Server = Server;
941

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/server_capabilities.js

10%
28
3
25
LineHitsSource
11var ServerCapabilities = function(isMasterResult) {
2 // Capabilities
30 var aggregationCursor = false;
40 var writeCommands = false;
50 var textSearch = false;
60 var authCommands = false;
70 var maxNumberOfDocsInBatch = 1000;
8
90 if(isMasterResult.minWireVersion >= 0) {
100 textSearch = true;
11 }
12
130 if(isMasterResult.maxWireVersion >= 1) {
140 aggregationCursor = true;
150 authCommands = true;
16 }
17
180 if(isMasterResult.maxWireVersion >= 2) {
190 writeCommands = true;
20 }
21
22 // If no min or max wire version set to 0
230 if(isMasterResult.minWireVersion == null) {
240 isMasterResult.minWireVersion = 0;
25 }
26
270 if(isMasterResult.maxWireVersion == null) {
280 isMasterResult.maxWireVersion = 0;
29 }
30
31 // Map up read only parameters
320 setup_get_property(this, "hasAggregationCursor", aggregationCursor);
330 setup_get_property(this, "hasWriteCommands", writeCommands);
340 setup_get_property(this, "hasTextSearch", textSearch);
350 setup_get_property(this, "hasAuthCommands", authCommands);
360 setup_get_property(this, "minWireVersion", isMasterResult.minWireVersion);
370 setup_get_property(this, "maxWireVersion", isMasterResult.maxWireVersion);
380 setup_get_property(this, "maxNumberOfDocsInBatch", maxNumberOfDocsInBatch);
39}
40
411var setup_get_property = function(object, name, value) {
420 Object.defineProperty(object, name, {
43 enumerable: true
440 , get: function () { return value; }
45 });
46}
47
481exports.ServerCapabilities = ServerCapabilities;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/connection/url_parser.js

1%
141
2
139
LineHitsSource
11var fs = require('fs'),
2 ReadPreference = require('./read_preference').ReadPreference;
3
41exports.parse = function(url, options) {
5 // Ensure we have a default options object if none set
60 options = options || {};
7 // Variables
80 var connection_part = '';
90 var auth_part = '';
100 var query_string_part = '';
110 var dbName = 'admin';
12
13 // Must start with mongodb
140 if(url.indexOf("mongodb://") != 0)
150 throw Error("URL must be in the format mongodb://user:pass@host:port/dbname");
16 // If we have a ? mark cut the query elements off
170 if(url.indexOf("?") != -1) {
180 query_string_part = url.substr(url.indexOf("?") + 1);
190 connection_part = url.substring("mongodb://".length, url.indexOf("?"))
20 } else {
210 connection_part = url.substring("mongodb://".length);
22 }
23
24 // Check if we have auth params
250 if(connection_part.indexOf("@") != -1) {
260 auth_part = connection_part.split("@")[0];
270 connection_part = connection_part.split("@")[1];
28 }
29
30 // Check if the connection string has a db
310 if(connection_part.indexOf(".sock") != -1) {
320 if(connection_part.indexOf(".sock/") != -1) {
330 dbName = connection_part.split(".sock/")[1];
340 connection_part = connection_part.split("/", connection_part.indexOf(".sock") + ".sock".length);
35 }
360 } else if(connection_part.indexOf("/") != -1) {
370 dbName = connection_part.split("/")[1];
380 connection_part = connection_part.split("/")[0];
39 }
40
41 // Result object
420 var object = {};
43
44 // Pick apart the authentication part of the string
450 var authPart = auth_part || '';
460 var auth = authPart.split(':', 2);
470 if(options['uri_decode_auth']){
480 auth[0] = decodeURIComponent(auth[0]);
490 if(auth[1]){
500 auth[1] = decodeURIComponent(auth[1]);
51 }
52 }
53
54 // Add auth to final object if we have 2 elements
550 if(auth.length == 2) object.auth = {user: auth[0], password: auth[1]};
56
57 // Variables used for temporary storage
580 var hostPart;
590 var urlOptions;
600 var servers;
610 var serverOptions = {socketOptions: {}};
620 var dbOptions = {read_preference_tags: []};
630 var replSetServersOptions = {socketOptions: {}};
64 // Add server options to final object
650 object.server_options = serverOptions;
660 object.db_options = dbOptions;
670 object.rs_options = replSetServersOptions;
680 object.mongos_options = {};
69
70 // Let's check if we are using a domain socket
710 if(url.match(/\.sock/)) {
72 // Split out the socket part
730 var domainSocket = url.substring(
74 url.indexOf("mongodb://") + "mongodb://".length
75 , url.lastIndexOf(".sock") + ".sock".length);
76 // Clean out any auth stuff if any
770 if(domainSocket.indexOf("@") != -1) domainSocket = domainSocket.split("@")[1];
780 servers = [{domain_socket: domainSocket}];
79 } else {
80 // Split up the db
810 hostPart = connection_part;
82 // Parse all server results
830 servers = hostPart.split(',').map(function(h) {
840 var hostPort = h.split(':', 2);
850 var _host = hostPort[0] || 'localhost';
860 var _port = hostPort[1] != null ? parseInt(hostPort[1], 10) : 27017;
87 // Check for localhost?safe=true style case
880 if(_host.indexOf("?") != -1) _host = _host.split(/\?/)[0];
89
90 // Return the mapped object
910 return {host: _host, port: _port};
92 });
93 }
94
95 // Get the db name
960 object.dbName = dbName || 'admin';
97 // Split up all the options
980 urlOptions = (query_string_part || '').split(/[&;]/);
99 // Ugh, we have to figure out which options go to which constructor manually.
1000 urlOptions.forEach(function(opt) {
1010 if(!opt) return;
1020 var splitOpt = opt.split('='), name = splitOpt[0], value = splitOpt[1];
103 // Options implementations
1040 switch(name) {
105 case 'slaveOk':
106 case 'slave_ok':
1070 serverOptions.slave_ok = (value == 'true');
1080 dbOptions.slaveOk = (value == 'true');
1090 break;
110 case 'maxPoolSize':
111 case 'poolSize':
1120 serverOptions.poolSize = parseInt(value, 10);
1130 replSetServersOptions.poolSize = parseInt(value, 10);
1140 break;
115 case 'autoReconnect':
116 case 'auto_reconnect':
1170 serverOptions.auto_reconnect = (value == 'true');
1180 break;
119 case 'minPoolSize':
1200 throw new Error("minPoolSize not supported");
121 case 'maxIdleTimeMS':
1220 throw new Error("maxIdleTimeMS not supported");
123 case 'waitQueueMultiple':
1240 throw new Error("waitQueueMultiple not supported");
125 case 'waitQueueTimeoutMS':
1260 throw new Error("waitQueueTimeoutMS not supported");
127 case 'uuidRepresentation':
1280 throw new Error("uuidRepresentation not supported");
129 case 'ssl':
1300 if(value == 'prefer') {
1310 serverOptions.ssl = value;
1320 replSetServersOptions.ssl = value;
1330 break;
134 }
1350 serverOptions.ssl = (value == 'true');
1360 replSetServersOptions.ssl = (value == 'true');
1370 break;
138 case 'replicaSet':
139 case 'rs_name':
1400 replSetServersOptions.rs_name = value;
1410 break;
142 case 'reconnectWait':
1430 replSetServersOptions.reconnectWait = parseInt(value, 10);
1440 break;
145 case 'retries':
1460 replSetServersOptions.retries = parseInt(value, 10);
1470 break;
148 case 'readSecondary':
149 case 'read_secondary':
1500 replSetServersOptions.read_secondary = (value == 'true');
1510 break;
152 case 'fsync':
1530 dbOptions.fsync = (value == 'true');
1540 break;
155 case 'journal':
1560 dbOptions.journal = (value == 'true');
1570 break;
158 case 'safe':
1590 dbOptions.safe = (value == 'true');
1600 break;
161 case 'nativeParser':
162 case 'native_parser':
1630 dbOptions.native_parser = (value == 'true');
1640 break;
165 case 'connectTimeoutMS':
1660 serverOptions.socketOptions.connectTimeoutMS = parseInt(value, 10);
1670 replSetServersOptions.socketOptions.connectTimeoutMS = parseInt(value, 10);
1680 break;
169 case 'socketTimeoutMS':
1700 serverOptions.socketOptions.socketTimeoutMS = parseInt(value, 10);
1710 replSetServersOptions.socketOptions.socketTimeoutMS = parseInt(value, 10);
1720 break;
173 case 'w':
1740 dbOptions.w = parseInt(value, 10);
1750 break;
176 case 'authSource':
1770 dbOptions.authSource = value;
1780 break;
179 case 'gssapiServiceName':
1800 dbOptions.gssapiServiceName = value;
1810 break;
182 case 'authMechanism':
1830 if(value == 'GSSAPI') {
184 // If no password provided decode only the principal
1850 if(object.auth == null) {
1860 var urlDecodeAuthPart = decodeURIComponent(authPart);
1870 if(urlDecodeAuthPart.indexOf("@") == -1) throw new Error("GSSAPI requires a provided principal");
1880 object.auth = {user: urlDecodeAuthPart, password: null};
189 } else {
1900 object.auth.user = decodeURIComponent(object.auth.user);
191 }
1920 } else if(value == 'MONGODB-X509') {
1930 object.auth = {user: decodeURIComponent(authPart)};
194 }
195
196 // Only support GSSAPI or MONGODB-CR for now
1970 if(value != 'GSSAPI'
198 && value != 'MONGODB-X509'
199 && value != 'MONGODB-CR'
200 && value != 'PLAIN')
2010 throw new Error("only GSSAPI, PLAIN, MONGODB-X509 or MONGODB-CR is supported by authMechanism");
202
203 // Authentication mechanism
2040 dbOptions.authMechanism = value;
2050 break;
206 case 'wtimeoutMS':
2070 dbOptions.wtimeoutMS = parseInt(value, 10);
2080 break;
209 case 'readPreference':
2100 if(!ReadPreference.isValid(value)) throw new Error("readPreference must be either primary/primaryPreferred/secondary/secondaryPreferred/nearest");
2110 dbOptions.read_preference = value;
2120 break;
213 case 'readPreferenceTags':
214 // Contains the tag object
2150 var tagObject = {};
2160 if(value == null || value == '') {
2170 dbOptions.read_preference_tags.push(tagObject);
2180 break;
219 }
220
221 // Split up the tags
2220 var tags = value.split(/\,/);
2230 for(var i = 0; i < tags.length; i++) {
2240 var parts = tags[i].trim().split(/\:/);
2250 tagObject[parts[0]] = parts[1];
226 }
227
228 // Set the preferences tags
2290 dbOptions.read_preference_tags.push(tagObject);
2300 break;
231 default:
2320 break;
233 }
234 });
235
236 // No tags: should be null (not [])
2370 if(dbOptions.read_preference_tags.length === 0) {
2380 dbOptions.read_preference_tags = null;
239 }
240
241 // Validate if there are an invalid write concern combinations
2420 if((dbOptions.w == -1 || dbOptions.w == 0) && (
243 dbOptions.journal == true
244 || dbOptions.fsync == true
2450 || dbOptions.safe == true)) throw new Error("w set to -1 or 0 cannot be combined with safe/w/journal/fsync")
246
247 // If no read preference set it to primary
2480 if(!dbOptions.read_preference) dbOptions.read_preference = 'primary';
249
250 // Add servers to result
2510 object.servers = servers;
252 // Returned parsed object
2530 return object;
254}
255

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/cursor.js

8%
394
32
362
LineHitsSource
11var QueryCommand = require('./commands/query_command').QueryCommand,
2 GetMoreCommand = require('./commands/get_more_command').GetMoreCommand,
3 KillCursorCommand = require('./commands/kill_cursor_command').KillCursorCommand,
4 Long = require('bson').Long,
5 ReadPreference = require('./connection/read_preference').ReadPreference,
6 CursorStream = require('./cursorstream'),
7 timers = require('timers'),
8 utils = require('./utils');
9
10// Set processor, setImmediate if 0.10 otherwise nextTick
111var processor = require('./utils').processor();
12
13/**
14 * Constructor for a cursor object that handles all the operations on query result
15 * using find. This cursor object is unidirectional and cannot traverse backwards. Clients should not be creating a cursor directly,
16 * but use find to acquire a cursor. (INTERNAL TYPE)
17 *
18 * Options
19 * - **skip** {Number} skip number of documents to skip.
20 * - **limit** {Number}, limit the number of results to return. -1 has a special meaning and is used by Db.eval. A value of 1 will also be treated as if it were -1.
21 * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc.
22 * - **hint** {Object}, hint force the query to use a specific index.
23 * - **explain** {Boolean}, explain return the explaination of the query.
24 * - **snapshot** {Boolean}, snapshot Snapshot mode assures no duplicates are returned.
25 * - **timeout** {Boolean}, timeout allow the query to timeout.
26 * - **tailable** {Boolean}, tailable allow the cursor to be tailable.
27 * - **awaitdata** {Boolean}, awaitdata allow the cursor to wait for data, only applicable for tailable cursor.
28 * - **oplogReplay** {Boolean}, sets an internal flag, only applicable for tailable cursor.
29 * - **batchSize** {Number}, batchSize the number of the subset of results to request the database to return for every request. This should initially be greater than 1 otherwise the database will automatically close the cursor. The batch size can be set to 1 with cursorInstance.batchSize after performing the initial query to the database.
30 * - **raw** {Boolean}, raw return all query documents as raw buffers (default false).
31 * - **read** {Boolean}, read specify override of read from source (primary/secondary).
32 * - **returnKey** {Boolean}, returnKey only return the index key.
33 * - **maxScan** {Number}, maxScan limit the number of items to scan.
34 * - **min** {Number}, min set index bounds.
35 * - **max** {Number}, max set index bounds.
36 * - **maxTimeMS** {Number}, number of miliseconds to wait before aborting the query.
37 * - **showDiskLoc** {Boolean}, showDiskLoc show disk location of results.
38 * - **comment** {String}, comment you can put a $comment field on a query to make looking in the profiler logs simpler.
39 * - **numberOfRetries** {Number}, numberOfRetries if using awaidata specifies the number of times to retry on timeout.
40 * - **dbName** {String}, dbName override the default dbName.
41 * - **tailableRetryInterval** {Number}, tailableRetryInterval specify the miliseconds between getMores on tailable cursor.
42 * - **exhaust** {Boolean}, exhaust have the server send all the documents at once as getMore packets.
43 * - **partial** {Boolean}, partial have the sharded system return a partial result from mongos.
44 *
45 * @class Represents a Cursor.
46 * @param {Db} db the database object to work with.
47 * @param {Collection} collection the collection to query.
48 * @param {Object} selector the query selector.
49 * @param {Object} fields an object containing what fields to include or exclude from objects returned.
50 * @param {Object} [options] additional options for the collection.
51*/
521function Cursor(db, collection, selector, fields, options) {
530 this.db = db;
540 this.collection = collection;
550 this.selector = selector;
560 this.fields = fields;
570 options = !options ? {} : options;
58
590 this.skipValue = options.skip == null ? 0 : options.skip;
600 this.limitValue = options.limit == null ? 0 : options.limit;
610 this.sortValue = options.sort;
620 this.hint = options.hint;
630 this.explainValue = options.explain;
640 this.snapshot = options.snapshot;
650 this.timeout = options.timeout == null ? true : options.timeout;
660 this.tailable = options.tailable;
670 this.awaitdata = options.awaitdata;
680 this.oplogReplay = options.oplogReplay;
690 this.numberOfRetries = options.numberOfRetries == null ? 5 : options.numberOfRetries;
700 this.currentNumberOfRetries = this.numberOfRetries;
710 this.batchSizeValue = options.batchSize == null ? 0 : options.batchSize;
720 this.raw = options.raw == null ? false : options.raw;
730 this.read = options.read == null ? ReadPreference.PRIMARY : options.read;
740 this.returnKey = options.returnKey;
750 this.maxScan = options.maxScan;
760 this.min = options.min;
770 this.max = options.max;
780 this.showDiskLoc = options.showDiskLoc;
790 this.comment = options.comment;
800 this.tailableRetryInterval = options.tailableRetryInterval || 100;
810 this.exhaust = options.exhaust || false;
820 this.partial = options.partial || false;
830 this.slaveOk = options.slaveOk || false;
840 this.maxTimeMSValue = options.maxTimeMS;
85
860 this.totalNumberOfRecords = 0;
870 this.items = [];
880 this.cursorId = Long.fromInt(0);
89
90 // This name
910 this.dbName = options.dbName;
92
93 // State variables for the cursor
940 this.state = Cursor.INIT;
95 // Keep track of the current query run
960 this.queryRun = false;
970 this.getMoreTimer = false;
98
99 // If we are using a specific db execute against it
1000 if(this.dbName != null) {
1010 this.collectionName = this.dbName + "." + this.collection.collectionName;
102 } else {
1030 this.collectionName = (this.db.databaseName ? this.db.databaseName + "." : '') + this.collection.collectionName;
104 }
105};
106
107/**
108 * Resets this cursor to its initial state. All settings like the query string,
109 * tailable, batchSizeValue, skipValue and limits are preserved.
110 *
111 * @return {Cursor} returns itself with rewind applied.
112 * @api public
113 */
1141Cursor.prototype.rewind = function() {
1150 var self = this;
116
1170 if (self.state != Cursor.INIT) {
1180 if (self.state != Cursor.CLOSED) {
1190 self.close(function() {});
120 }
121
1220 self.numberOfReturned = 0;
1230 self.totalNumberOfRecords = 0;
1240 self.items = [];
1250 self.cursorId = Long.fromInt(0);
1260 self.state = Cursor.INIT;
1270 self.queryRun = false;
128 }
129
1300 return self;
131};
132
133
134/**
135 * Returns an array of documents. The caller is responsible for making sure that there
136 * is enough memory to store the results. Note that the array only contain partial
137 * results when this cursor had been previouly accessed. In that case,
138 * cursor.rewind() can be used to reset the cursor.
139 *
140 * @param {Function} callback This will be called after executing this method successfully. The first parameter will contain the Error object if an error occured, or null otherwise. The second parameter will contain an array of BSON deserialized objects as a result of the query.
141 * @return {null}
142 * @api public
143 */
1441Cursor.prototype.toArray = function(callback) {
1450 var self = this;
146
1470 if(!callback) {
1480 throw new Error('callback is mandatory');
149 }
150
1510 if(this.tailable) {
1520 callback(new Error("Tailable cursor cannot be converted to array"), null);
1530 } else if(this.state != Cursor.CLOSED) {
154 // return toArrayExhaust(self, callback);
155 // If we are using exhaust we can't use the quick fire method
1560 if(self.exhaust) return toArrayExhaust(self, callback);
157 // Quick fire using trampoline to avoid nextTick
1580 self.nextObject({noReturn: true}, function(err, result) {
1590 if(err) return callback(utils.toError(err), null);
1600 if(self.cursorId.toString() == "0") {
1610 self.state = Cursor.CLOSED;
1620 return callback(null, self.items);
163 }
164
165 // Let's issue getMores until we have no more records waiting
1660 getAllByGetMore(self, function(err, done) {
1670 self.state = Cursor.CLOSED;
1680 if(err) return callback(utils.toError(err), null);
169 // Let's release the internal list
1700 var items = self.items;
1710 self.items = null;
172 // Return all the items
1730 callback(null, items);
174 });
175 })
176
177 } else {
1780 callback(new Error("Cursor is closed"), null);
179 }
180}
181
1821var toArrayExhaust = function(self, callback) {
1830 var items = [];
184
1850 self.each(function(err, item) {
1860 if(err != null) {
1870 return callback(utils.toError(err), null);
188 }
189
1900 if(item != null && Array.isArray(items)) {
1910 items.push(item);
192 } else {
1930 var resultItems = items;
1940 items = null;
1950 self.items = [];
1960 callback(null, resultItems);
197 }
198 });
199}
200
2011var getAllByGetMore = function(self, callback) {
2020 getMore(self, {noReturn: true}, function(err, result) {
2030 if(err) return callback(utils.toError(err));
2040 if(result == null) return callback(null, null);
2050 if(self.cursorId.toString() == "0") return callback(null, null);
2060 getAllByGetMore(self, callback);
207 })
208};
209
210/**
211 * Iterates over all the documents for this cursor. As with **{cursor.toArray}**,
212 * not all of the elements will be iterated if this cursor had been previouly accessed.
213 * In that case, **{cursor.rewind}** can be used to reset the cursor. However, unlike
214 * **{cursor.toArray}**, the cursor will only hold a maximum of batch size elements
215 * at any given time if batch size is specified. Otherwise, the caller is responsible
216 * for making sure that the entire result can fit the memory.
217 *
218 * @param {Function} callback this will be called for while iterating every document of the query result. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the document.
219 * @return {null}
220 * @api public
221 */
2221Cursor.prototype.each = function(callback) {
2230 var self = this;
2240 var fn;
225
2260 if (!callback) {
2270 throw new Error('callback is mandatory');
228 }
229
2300 if(this.state != Cursor.CLOSED) {
231 // If we are using exhaust we can't use the quick fire method
2320 if(self.exhaust) return eachExhaust(self, callback);
233 // Quick fire using trampoline to avoid nextTick
2340 if(this.items.length > 0) {
235 // Trampoline all the entries
2360 while(fn = loop(self, callback)) fn(self, callback);
237 // Call each again
2380 self.each(callback);
239 } else {
2400 self.nextObject(function(err, item) {
241
2420 if(err) {
2430 self.state = Cursor.CLOSED;
2440 return callback(utils.toError(err), item);
245 }
246
2470 if(item == null) return callback(null, null);
2480 callback(null, item);
2490 self.each(callback);
250 })
251 }
252 } else {
2530 callback(new Error("Cursor is closed"), null);
254 }
255};
256
257// Special for exhaust command as we don't initiate the actual result sets
258// the server just sends them as they arrive meaning we need to get the IO event
259// loop happen so we can receive more data from the socket or we return to early
260// after the first fetch and loose all the incoming getMore's automatically issued
261// from the server.
2621var eachExhaust = function(self, callback) {
263 //FIX: stack overflow (on deep callback) (cred: https://github.com/limp/node-mongodb-native/commit/27da7e4b2af02035847f262b29837a94bbbf6ce2)
2640 processor(function(){
265 // Fetch the next object until there is no more objects
2660 self.nextObject(function(err, item) {
2670 if(err != null) return callback(err, null);
2680 if(item != null) {
2690 callback(null, item);
2700 eachExhaust(self, callback);
271 } else {
272 // Close the cursor if done
2730 self.state = Cursor.CLOSED;
2740 callback(err, null);
275 }
276 });
277 });
278}
279
280// Trampoline emptying the number of retrieved items
281// without incurring a nextTick operation
2821var loop = function(self, callback) {
283 // No more items we are done
2840 if(self.items.length == 0) return;
285 // Get the next document
2860 var doc = self.items.shift();
287 // Callback
2880 callback(null, doc);
289 // Loop
2900 return loop;
291}
292
293/**
294 * Determines how many result the query for this cursor will return
295 *
296 * @param {Boolean} applySkipLimit if set to true will apply the skip and limits set on the cursor. Defaults to false.
297 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the number of results or null if an error occured.
298 * @return {null}
299 * @api public
300 */
3011Cursor.prototype.count = function(applySkipLimit, callback) {
3020 if(typeof applySkipLimit == 'function') {
3030 callback = applySkipLimit;
3040 applySkipLimit = false;
305 }
306
3070 var options = {};
3080 if(applySkipLimit) {
3090 if(typeof this.skipValue == 'number') options.skip = this.skipValue;
3100 if(typeof this.limitValue == 'number') options.limit = this.limitValue;
311 }
312
313 // If maxTimeMS set
3140 if(typeof this.maxTimeMSValue == 'number') options.maxTimeMS = this.maxTimeMSValue;
315
316 // Call count command
3170 this.collection.count(this.selector, options, callback);
318};
319
320/**
321 * Sets the sort parameter of this cursor to the given value.
322 *
323 * This method has the following method signatures:
324 * (keyOrList, callback)
325 * (keyOrList, direction, callback)
326 *
327 * @param {String|Array|Object} keyOrList This can be a string or an array. If passed as a string, the string will be the field to sort. If passed an array, each element will represent a field to be sorted and should be an array that contains the format [string, direction].
328 * @param {String|Number} direction this determines how the results are sorted. "asc", "ascending" or 1 for asceding order while "desc", "desceding or -1 for descending order. Note that the strings are case insensitive.
329 * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
330 * @return {Cursor} an instance of this object.
331 * @api public
332 */
3331Cursor.prototype.sort = function(keyOrList, direction, callback) {
3340 callback = callback || function(){};
3350 if(typeof direction === "function") { callback = direction; direction = null; }
336
3370 if(this.tailable) {
3380 callback(new Error("Tailable cursor doesn't support sorting"), null);
3390 } else if(this.queryRun == true || this.state == Cursor.CLOSED) {
3400 callback(new Error("Cursor is closed"), null);
341 } else {
3420 var order = keyOrList;
343
3440 if(direction != null) {
3450 order = [[keyOrList, direction]];
346 }
347
3480 this.sortValue = order;
3490 callback(null, this);
350 }
3510 return this;
352};
353
354/**
355 * Sets the limit parameter of this cursor to the given value.
356 *
357 * @param {Number} limit the new limit.
358 * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
359 * @return {Cursor} an instance of this object.
360 * @api public
361 */
3621Cursor.prototype.limit = function(limit, callback) {
3630 if(this.tailable) {
3640 if(callback) {
3650 callback(new Error("Tailable cursor doesn't support limit"), null);
366 } else {
3670 throw new Error("Tailable cursor doesn't support limit");
368 }
3690 } else if(this.queryRun == true || this.state == Cursor.CLOSED) {
3700 if(callback) {
3710 callback(new Error("Cursor is closed"), null);
372 } else {
3730 throw new Error("Cursor is closed");
374 }
375 } else {
3760 if(limit != null && limit.constructor != Number) {
3770 if(callback) {
3780 callback(new Error("limit requires an integer"), null);
379 } else {
3800 throw new Error("limit requires an integer");
381 }
382 } else {
3830 this.limitValue = limit;
3840 if(callback) return callback(null, this);
385 }
386 }
387
3880 return this;
389};
390
391/**
392 * Specifies a time limit for a query operation. After the specified
393 * time is exceeded, the operation will be aborted and an error will be
394 * returned to the client. If maxTimeMS is null, no limit is applied.
395 *
396 * @param {Number} maxTimeMS the maxTimeMS for the query.
397 * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
398 * @return {Cursor} an instance of this object.
399 * @api public
400 */
4011Cursor.prototype.maxTimeMS = function(maxTimeMS, callback) {
4020 if(typeof maxTimeMS != 'number') {
4030 throw new Error("maxTimeMS must be a number");
404 }
405
406 // Save the maxTimeMS option
4070 this.maxTimeMSValue = maxTimeMS;
408 // Return the cursor for chaining
4090 return this;
410};
411
412/**
413 * Sets the read preference for the cursor
414 *
415 * @param {String} the read preference for the cursor, one of Server.READ_PRIMARY, Server.READ_SECONDARY, Server.READ_SECONDARY_ONLY
416 * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the read preference given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
417 * @return {Cursor} an instance of this object.
418 * @api public
419 */
4201Cursor.prototype.setReadPreference = function(readPreference, tags, callback) {
4210 if(typeof tags == 'function') callback = tags;
422
4230 var _mode = readPreference != null && typeof readPreference == 'object' ? readPreference.mode : readPreference;
424
4250 if(this.queryRun == true || this.state == Cursor.CLOSED) {
4260 if(callback == null) throw new Error("Cannot change read preference on executed query or closed cursor");
4270 callback(new Error("Cannot change read preference on executed query or closed cursor"));
4280 } else if(_mode != null && _mode != 'primary'
429 && _mode != 'secondaryOnly' && _mode != 'secondary'
430 && _mode != 'nearest' && _mode != 'primaryPreferred' && _mode != 'secondaryPreferred') {
4310 if(callback == null) throw new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported");
4320 callback(new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported"));
433 } else {
4340 this.read = readPreference;
4350 if(callback != null) callback(null, this);
436 }
437
4380 return this;
439}
440
441/**
442 * Sets the skip parameter of this cursor to the given value.
443 *
444 * @param {Number} skip the new skip value.
445 * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the skip value given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
446 * @return {Cursor} an instance of this object.
447 * @api public
448 */
4491Cursor.prototype.skip = function(skip, callback) {
4500 callback = callback || function(){};
451
4520 if(this.tailable) {
4530 callback(new Error("Tailable cursor doesn't support skip"), null);
4540 } else if(this.queryRun == true || this.state == Cursor.CLOSED) {
4550 callback(new Error("Cursor is closed"), null);
456 } else {
4570 if(skip != null && skip.constructor != Number) {
4580 callback(new Error("skip requires an integer"), null);
459 } else {
4600 this.skipValue = skip;
4610 callback(null, this);
462 }
463 }
464
4650 return this;
466};
467
468/**
469 * Sets the batch size parameter of this cursor to the given value.
470 *
471 * @param {Number} batchSize the new batch size.
472 * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the batchSize given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
473 * @return {Cursor} an instance of this object.
474 * @api public
475 */
4761Cursor.prototype.batchSize = function(batchSize, callback) {
4770 if(this.state == Cursor.CLOSED) {
4780 if(callback != null) {
4790 return callback(new Error("Cursor is closed"), null);
480 } else {
4810 throw new Error("Cursor is closed");
482 }
4830 } else if(batchSize != null && batchSize.constructor != Number) {
4840 if(callback != null) {
4850 return callback(new Error("batchSize requires an integer"), null);
486 } else {
4870 throw new Error("batchSize requires an integer");
488 }
489 } else {
4900 this.batchSizeValue = batchSize;
4910 if(callback != null) return callback(null, this);
492 }
493
4940 return this;
495};
496
497/**
498 * The limit used for the getMore command
499 *
500 * @return {Number} The number of records to request per batch.
501 * @ignore
502 * @api private
503 */
5041var limitRequest = function(self) {
5050 var requestedLimit = self.limitValue;
5060 var absLimitValue = Math.abs(self.limitValue);
5070 var absBatchValue = Math.abs(self.batchSizeValue);
508
5090 if(absLimitValue > 0) {
5100 if (absBatchValue > 0) {
5110 requestedLimit = Math.min(absLimitValue, absBatchValue);
512 }
513 } else {
5140 requestedLimit = self.batchSizeValue;
515 }
516
5170 return requestedLimit;
518};
519
520
521/**
522 * Generates a QueryCommand object using the parameters of this cursor.
523 *
524 * @return {QueryCommand} The command object
525 * @ignore
526 * @api private
527 */
5281var generateQueryCommand = function(self) {
529 // Unpack the options
5300 var queryOptions = QueryCommand.OPTS_NONE;
5310 if(!self.timeout) {
5320 queryOptions |= QueryCommand.OPTS_NO_CURSOR_TIMEOUT;
533 }
534
5350 if(self.tailable != null) {
5360 queryOptions |= QueryCommand.OPTS_TAILABLE_CURSOR;
5370 self.skipValue = self.limitValue = 0;
538
539 // if awaitdata is set
5400 if(self.awaitdata != null) {
5410 queryOptions |= QueryCommand.OPTS_AWAIT_DATA;
542 }
543
544 // This sets an internal undocumented flag. Clients should not depend on its
545 // behavior!
5460 if(self.oplogReplay != null) {
5470 queryOptions |= QueryCommand.OPTS_OPLOG_REPLAY;
548 }
549 }
550
5510 if(self.exhaust) {
5520 queryOptions |= QueryCommand.OPTS_EXHAUST;
553 }
554
555 // Unpack the read preference to set slave ok correctly
5560 var read = self.read instanceof ReadPreference ? self.read.mode : self.read;
557
558 // if(self.read == 'secondary')
5590 if(read == ReadPreference.PRIMARY_PREFERRED
560 || read == ReadPreference.SECONDARY
561 || read == ReadPreference.SECONDARY_PREFERRED
562 || read == ReadPreference.NEAREST) {
5630 queryOptions |= QueryCommand.OPTS_SLAVE;
564 }
565
566 // Override slaveOk from the user
5670 if(self.slaveOk) {
5680 queryOptions |= QueryCommand.OPTS_SLAVE;
569 }
570
5710 if(self.partial) {
5720 queryOptions |= QueryCommand.OPTS_PARTIAL;
573 }
574
575 // limitValue of -1 is a special case used by Db#eval
5760 var numberToReturn = self.limitValue == -1 ? -1 : limitRequest(self);
577
578 // Check if we need a special selector
5790 if(self.sortValue != null || self.explainValue != null || self.hint != null || self.snapshot != null
580 || self.returnKey != null || self.maxScan != null || self.min != null || self.max != null
581 || self.showDiskLoc != null || self.comment != null || typeof self.maxTimeMSValue == 'number') {
582
583 // Build special selector
5840 var specialSelector = {'$query':self.selector};
5850 if(self.sortValue != null) specialSelector['orderby'] = utils.formattedOrderClause(self.sortValue);
5860 if(self.hint != null && self.hint.constructor == Object) specialSelector['$hint'] = self.hint;
5870 if(self.snapshot != null) specialSelector['$snapshot'] = true;
5880 if(self.returnKey != null) specialSelector['$returnKey'] = self.returnKey;
5890 if(self.maxScan != null) specialSelector['$maxScan'] = self.maxScan;
5900 if(self.min != null) specialSelector['$min'] = self.min;
5910 if(self.max != null) specialSelector['$max'] = self.max;
5920 if(self.showDiskLoc != null) specialSelector['$showDiskLoc'] = self.showDiskLoc;
5930 if(self.comment != null) specialSelector['$comment'] = self.comment;
594
595 // If we are querying the $cmd collection we need to add maxTimeMS as a field
596 // otherwise for a normal query it's a "special selector" $maxTimeMS
5970 if(typeof self.maxTimeMSValue == 'number'
598 && self.collectionName.indexOf('.$cmd') != -1) {
5990 specialSelector['maxTimeMS'] = self.maxTimeMSValue;
6000 } else if(typeof self.maxTimeMSValue == 'number'
601 && self.collectionName.indexOf('.$cmd') == -1) {
6020 specialSelector['$maxTimeMS'] = self.maxTimeMSValue;
603 }
604
605 // If we have explain set only return a single document with automatic cursor close
6060 if(self.explainValue != null) {
6070 numberToReturn = (-1)*Math.abs(numberToReturn);
6080 specialSelector['$explain'] = true;
609 }
610
611 // Return the query
6120 return new QueryCommand(self.db, self.collectionName, queryOptions, self.skipValue, numberToReturn, specialSelector, self.fields);
613 } else {
6140 return new QueryCommand(self.db, self.collectionName, queryOptions, self.skipValue, numberToReturn, self.selector, self.fields);
615 }
616};
617
618/**
619 * @return {Object} Returns an object containing the sort value of this cursor with
620 * the proper formatting that can be used internally in this cursor.
621 * @ignore
622 * @api private
623 */
6241Cursor.prototype.formattedOrderClause = function() {
6250 return utils.formattedOrderClause(this.sortValue);
626};
627
628/**
629 * Converts the value of the sort direction into its equivalent numerical value.
630 *
631 * @param sortDirection {String|number} Range of acceptable values:
632 * 'ascending', 'descending', 'asc', 'desc', 1, -1
633 *
634 * @return {number} The equivalent numerical value
635 * @throws Error if the given sortDirection is invalid
636 * @ignore
637 * @api private
638 */
6391Cursor.prototype.formatSortValue = function(sortDirection) {
6400 return utils.formatSortValue(sortDirection);
641};
642
643/**
644 * Gets the next document from the cursor.
645 *
646 * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object on error while the second parameter will contain a document from the returned result or null if there are no more results.
647 * @api public
648 */
6491Cursor.prototype.nextObject = function(options, callback) {
6500 var self = this;
651
6520 if(typeof options == 'function') {
6530 callback = options;
6540 options = {};
655 }
656
6570 if(self.state == Cursor.INIT) {
6580 var cmd;
6590 try {
6600 cmd = generateQueryCommand(self);
661 } catch (err) {
6620 return callback(err, null);
663 }
664
665 // No need to check the keys
6660 var queryOptions = {exhaust: self.exhaust
667 , raw:self.raw
668 , read:self.read
669 , connection:self.connection
670 , checkKeys: false};
671
672 // Execute command
6730 var commandHandler = function(err, result) {
674 // If on reconnect, the command got given a different connection, switch
675 // the whole cursor to it.
6760 self.connection = queryOptions.connection;
6770 self.state = Cursor.OPEN;
6780 if(err != null && result == null) return callback(utils.toError(err), null);
679
6800 if(err == null && (result == null || result.documents == null || !Array.isArray(result.documents))) {
6810 return self.close(function() {callback(new Error("command failed to return results"), null);});
682 }
683
6840 if(err == null && result && result.documents[0] && result.documents[0]['$err']) {
6850 return self.close(function() {callback(utils.toError(result.documents[0]['$err']), null);});
686 }
687
6880 if(err == null && result && result.documents[0] && result.documents[0]['errmsg']) {
6890 return self.close(function() {callback(utils.toError(result.documents[0]), null);});
690 }
691
6920 self.queryRun = true;
6930 self.state = Cursor.OPEN; // Adjust the state of the cursor
6940 self.cursorId = result.cursorId;
6950 self.totalNumberOfRecords = result.numberReturned;
696
697 // Add the new documents to the list of items, using forloop to avoid
698 // new array allocations and copying
6990 for(var i = 0; i < result.documents.length; i++) {
7000 self.items.push(result.documents[i]);
701 }
702
703 // If we have noReturn set just return (not modifying the internal item list)
704 // used for toArray
7050 if(options.noReturn) {
7060 return callback(null, true);
707 }
708
709 // Ignore callbacks until the cursor is dead for exhausted
7100 if(self.exhaust && result.cursorId.toString() == "0") {
7110 self.nextObject(callback);
7120 } else if(self.exhaust == false || self.exhaust == null) {
7130 self.nextObject(callback);
714 }
715 };
716
717 // If we have no connection set on this cursor check one out
7180 if(self.connection == null) {
7190 try {
7200 self.connection = self.db.serverConfig.checkoutReader(this.read);
721 // Add to the query options
7220 queryOptions.connection = self.connection;
723 } catch(err) {
7240 return callback(utils.toError(err), null);
725 }
726 }
727
728 // Execute the command
7290 self.db._executeQueryCommand(cmd, queryOptions, commandHandler);
730 // Set the command handler to null
7310 commandHandler = null;
7320 } else if(self.items.length) {
7330 callback(null, self.items.shift());
7340 } else if(self.cursorId.greaterThan(Long.fromInt(0))) {
7350 getMore(self, callback);
736 } else {
737 // Force cursor to stay open
7380 return self.close(function() {callback(null, null);});
739 }
740}
741
742/**
743 * Gets more results from the database if any.
744 *
745 * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object on error while the second parameter will contain a document from the returned result or null if there are no more results.
746 * @ignore
747 * @api private
748 */
7491var getMore = function(self, options, callback) {
7500 var limit = 0;
751
7520 if(typeof options == 'function') {
7530 callback = options;
7540 options = {};
755 }
756
7570 if(self.state == Cursor.GET_MORE) return callback(null, null);
758
759 // Set get more in progress
7600 self.state = Cursor.GET_MORE;
761
762 // Set options
7630 if (!self.tailable && self.limitValue > 0) {
7640 limit = self.limitValue - self.totalNumberOfRecords;
7650 if (limit < 1) {
7660 self.close(function() {callback(null, null);});
7670 return;
768 }
769 }
770
7710 try {
7720 var getMoreCommand = new GetMoreCommand(
773 self.db
774 , self.collectionName
775 , limitRequest(self)
776 , self.cursorId
777 );
778
779 // Set up options
7800 var command_options = {read: self.read, raw: self.raw, connection:self.connection };
781
782 // Execute the command
7830 self.db._executeQueryCommand(getMoreCommand, command_options, function(err, result) {
7840 var cbValue;
785
786 // Get more done
7870 self.state = Cursor.OPEN;
788
7890 if(err != null) {
7900 self.state = Cursor.CLOSED;
7910 return callback(utils.toError(err), null);
792 }
793
794 // Ensure we get a valid result
7950 if(!result || !result.documents) {
7960 self.state = Cursor.CLOSED;
7970 return callback(utils.toError("command failed to return results"), null)
798 }
799
800 // If the QueryFailure flag is set
8010 if((result.responseFlag & (1 << 1)) != 0) {
8020 self.state = Cursor.CLOSED;
8030 return callback(utils.toError("QueryFailure flag set on getmore command"), null);
804 }
805
8060 try {
8070 var isDead = 1 === result.responseFlag && result.cursorId.isZero();
808
8090 self.cursorId = result.cursorId;
8100 self.totalNumberOfRecords += result.numberReturned;
811
812 // Determine if there's more documents to fetch
8130 if(result.numberReturned > 0) {
8140 if (self.limitValue > 0) {
8150 var excessResult = self.totalNumberOfRecords - self.limitValue;
816
8170 if (excessResult > 0) {
8180 result.documents.splice(-1 * excessResult, excessResult);
819 }
820 }
821
822 // Reset the tries for awaitdata if we are using it
8230 self.currentNumberOfRetries = self.numberOfRetries;
824 // Get the documents
8250 for(var i = 0; i < result.documents.length; i++) {
8260 self.items.push(result.documents[i]);
827 }
828
829 // Don's shift a document out as we need it for toArray
8300 if(options.noReturn) {
8310 cbValue = true;
832 } else {
8330 cbValue = self.items.shift();
834 }
8350 } else if(self.tailable && !isDead && self.awaitdata) {
836 // Excute the tailable cursor once more, will timeout after ~4 sec if awaitdata used
8370 self.currentNumberOfRetries = self.currentNumberOfRetries - 1;
8380 if(self.currentNumberOfRetries == 0) {
8390 self.close(function() {
8400 callback(new Error("tailable cursor timed out"), null);
841 });
842 } else {
8430 getMore(self, callback);
844 }
8450 } else if(self.tailable && !isDead) {
8460 self.getMoreTimer = setTimeout(function() { getMore(self, callback); }, self.tailableRetryInterval);
847 } else {
8480 self.close(function() {callback(null, null); });
849 }
850
8510 result = null;
852 } catch(err) {
8530 callback(utils.toError(err), null);
854 }
8550 if (cbValue != null) callback(null, cbValue);
856 });
857
8580 getMoreCommand = null;
859 } catch(err) {
860 // Get more done
8610 self.state = Cursor.OPEN;
862
8630 var handleClose = function() {
8640 callback(utils.toError(err), null);
865 };
866
8670 self.close(handleClose);
8680 handleClose = null;
869 }
870}
871
872/**
873 * Gets a detailed information about how the query is performed on this cursor and how
874 * long it took the database to process it.
875 *
876 * @param {Function} callback this will be called after executing this method. The first parameter will always be null while the second parameter will be an object containing the details.
877 * @api public
878 */
8791Cursor.prototype.explain = function(callback) {
8800 var limit = (-1)*Math.abs(this.limitValue);
881
882 // Create a new cursor and fetch the plan
8830 var cursor = new Cursor(this.db, this.collection, this.selector, this.fields, {
884 skip: this.skipValue
885 , limit:limit
886 , sort: this.sortValue
887 , hint: this.hint
888 , explain: true
889 , snapshot: this.snapshot
890 , timeout: this.timeout
891 , tailable: this.tailable
892 , batchSize: this.batchSizeValue
893 , slaveOk: this.slaveOk
894 , raw: this.raw
895 , read: this.read
896 , returnKey: this.returnKey
897 , maxScan: this.maxScan
898 , min: this.min
899 , max: this.max
900 , showDiskLoc: this.showDiskLoc
901 , comment: this.comment
902 , awaitdata: this.awaitdata
903 , oplogReplay: this.oplogReplay
904 , numberOfRetries: this.numberOfRetries
905 , dbName: this.dbName
906 });
907
908 // Fetch the explaination document
9090 cursor.nextObject(function(err, item) {
9100 if(err != null) return callback(utils.toError(err), null);
911 // close the cursor
9120 cursor.close(function(err, result) {
9130 if(err != null) return callback(utils.toError(err), null);
9140 callback(null, item);
915 });
916 });
917};
918
919/**
920 * Returns a Node ReadStream interface for this cursor.
921 *
922 * Options
923 * - **transform** {Function} function of type function(object) { return transformed }, allows for transformation of data before emitting.
924 *
925 * @return {CursorStream} returns a stream object.
926 * @api public
927 */
9281Cursor.prototype.stream = function stream(options) {
9290 return new CursorStream(this, options);
930}
931
932/**
933 * Close the cursor.
934 *
935 * @param {Function} callback this will be called after executing this method. The first parameter will always contain null while the second parameter will contain a reference to this cursor.
936 * @return {null}
937 * @api public
938 */
9391Cursor.prototype.close = function(callback) {
9400 var self = this
9410 this.getMoreTimer && clearTimeout(this.getMoreTimer);
942 // Close the cursor if not needed
9430 if(this.cursorId instanceof Long && this.cursorId.greaterThan(Long.fromInt(0))) {
9440 try {
9450 var command = new KillCursorCommand(this.db, [this.cursorId]);
946 // Added an empty callback to ensure we don't throw any null exceptions
9470 this.db._executeQueryCommand(command, {read:self.read, raw:self.raw, connection:self.connection});
948 } catch(err) {}
949 }
950
951 // Null out the connection
9520 self.connection = null;
953 // Reset cursor id
9540 this.cursorId = Long.fromInt(0);
955 // Set to closed status
9560 this.state = Cursor.CLOSED;
957
9580 if(callback) {
9590 callback(null, self);
9600 self.items = [];
961 }
962
9630 return this;
964};
965
966/**
967 * Check if the cursor is closed or open.
968 *
969 * @return {Boolean} returns the state of the cursor.
970 * @api public
971 */
9721Cursor.prototype.isClosed = function() {
9730 return this.state == Cursor.CLOSED ? true : false;
974};
975
976/**
977 * Init state
978 *
979 * @classconstant INIT
980 **/
9811Cursor.INIT = 0;
982
983/**
984 * Cursor open
985 *
986 * @classconstant OPEN
987 **/
9881Cursor.OPEN = 1;
989
990/**
991 * Cursor closed
992 *
993 * @classconstant CLOSED
994 **/
9951Cursor.CLOSED = 2;
996
997/**
998 * Cursor performing a get more
999 *
1000 * @classconstant OPEN
1001 **/
10021Cursor.GET_MORE = 3;
1003
1004/**
1005 * @ignore
1006 * @api private
1007 */
10081exports.Cursor = Cursor;
1009

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/cursorstream.js

25%
55
14
41
LineHitsSource
11var timers = require('timers');
2
3// Set processor, setImmediate if 0.10 otherwise nextTick
41var processor = require('./utils').processor();
5
6/**
7 * Module dependecies.
8 */
91var Stream = require('stream').Stream;
10
11/**
12 * CursorStream
13 *
14 * Returns a stream interface for the **cursor**.
15 *
16 * Options
17 * - **transform** {Function} function of type function(object) { return transformed }, allows for transformation of data before emitting.
18 *
19 * Events
20 * - **data** {function(item) {}} the data event triggers when a document is ready.
21 * - **error** {function(err) {}} the error event triggers if an error happens.
22 * - **close** {function() {}} the end event triggers when there is no more documents available.
23 *
24 * @class Represents a CursorStream.
25 * @param {Cursor} cursor a cursor object that the stream wraps.
26 * @return {Stream}
27 */
281function CursorStream(cursor, options) {
290 if(!(this instanceof CursorStream)) return new CursorStream(cursor);
300 options = options ? options : {};
31
320 Stream.call(this);
33
340 this.readable = true;
350 this.paused = false;
360 this._cursor = cursor;
370 this._destroyed = null;
380 this.options = options;
39
40 // give time to hook up events
410 var self = this;
420 process.nextTick(function() {
430 self._init();
44 });
45}
46
47/**
48 * Inherit from Stream
49 * @ignore
50 * @api private
51 */
521CursorStream.prototype.__proto__ = Stream.prototype;
53
54/**
55 * Flag stating whether or not this stream is readable.
56 */
571CursorStream.prototype.readable;
58
59/**
60 * Flag stating whether or not this stream is paused.
61 */
621CursorStream.prototype.paused;
63
64/**
65 * Initialize the cursor.
66 * @ignore
67 * @api private
68 */
691CursorStream.prototype._init = function () {
700 if (this._destroyed) return;
710 this._next();
72}
73
74/**
75 * Pull the next document from the cursor.
76 * @ignore
77 * @api private
78 */
791CursorStream.prototype._next = function () {
800 if(this.paused || this._destroyed) return;
81
820 var self = this;
83 // Get the next object
840 processor(function() {
850 if(self.paused || self._destroyed) return;
86
870 self._cursor.nextObject(function (err, doc) {
880 self._onNextObject(err, doc);
89 });
90 });
91}
92
93/**
94 * Handle each document as its returned from the cursor.
95 * @ignore
96 * @api private
97 */
981CursorStream.prototype._onNextObject = function (err, doc) {
990 if(err) return this.destroy(err);
100
101 // when doc is null we hit the end of the cursor
1020 if(!doc && (this._cursor.state == 1 || this._cursor.state == 2)) {
1030 this.emit('end')
1040 return this.destroy();
1050 } else if(doc) {
1060 var data = typeof this.options.transform == 'function' ? this.options.transform(doc) : doc;
1070 this.emit('data', data);
1080 this._next();
109 }
110}
111
112/**
113 * Pauses the stream.
114 *
115 * @api public
116 */
1171CursorStream.prototype.pause = function () {
1180 this.paused = true;
119}
120
121/**
122 * Resumes the stream.
123 *
124 * @api public
125 */
1261CursorStream.prototype.resume = function () {
1270 var self = this;
128
129 // Don't do anything if we are not paused
1300 if(!this.paused) return;
1310 if(!this._cursor.state == 3) return;
132
1330 process.nextTick(function() {
1340 self.paused = false;
135 // Only trigger more fetching if the cursor is open
1360 self._next();
137 })
138}
139
140/**
141 * Destroys the stream, closing the underlying
142 * cursor. No more events will be emitted.
143 *
144 * @api public
145 */
1461CursorStream.prototype.destroy = function (err) {
1470 if (this._destroyed) return;
1480 this._destroyed = true;
1490 this.readable = false;
150
1510 this._cursor.close();
152
1530 if(err) {
1540 this.emit('error', err);
155 }
156
1570 this.emit('close');
158}
159
160// TODO - maybe implement the raw option to pass binary?
161//CursorStream.prototype.setEncoding = function () {
162//}
163
1641module.exports = exports = CursorStream;
165

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/db.js

8%
753
61
692
LineHitsSource
1/**
2 * Module dependencies.
3 * @ignore
4 */
51var QueryCommand = require('./commands/query_command').QueryCommand
6 , DbCommand = require('./commands/db_command').DbCommand
7 , MongoReply = require('./responses/mongo_reply').MongoReply
8 , Admin = require('./admin').Admin
9 , Collection = require('./collection').Collection
10 , Server = require('./connection/server').Server
11 , ReplSet = require('./connection/repl_set/repl_set').ReplSet
12 , ReadPreference = require('./connection/read_preference').ReadPreference
13 , Mongos = require('./connection/mongos').Mongos
14 , Cursor = require('./cursor').Cursor
15 , EventEmitter = require('events').EventEmitter
16 , inherits = require('util').inherits
17 , crypto = require('crypto')
18 , timers = require('timers')
19 , utils = require('./utils')
20
21 // Authentication methods
22 , mongodb_cr_authenticate = require('./auth/mongodb_cr.js').authenticate
23 , mongodb_gssapi_authenticate = require('./auth/mongodb_gssapi.js').authenticate
24 , mongodb_sspi_authenticate = require('./auth/mongodb_sspi.js').authenticate
25 , mongodb_plain_authenticate = require('./auth/mongodb_plain.js').authenticate
26 , mongodb_x509_authenticate = require('./auth/mongodb_x509.js').authenticate;
27
281var hasKerberos = false;
29// Check if we have a the kerberos library
301try {
311 require('kerberos');
321 hasKerberos = true;
33} catch(err) {}
34
35// Set processor, setImmediate if 0.10 otherwise nextTick
361var processor = require('./utils').processor();
37
38/**
39 * Create a new Db instance.
40 *
41 * Options
42 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
43 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
44 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
45 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
46 * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
47 * - **native_parser** {Boolean, default:false}, use c++ bson parser.
48 * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client.
49 * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
50 * - **serializeFunctions** {Boolean, default:false}, serialize functions.
51 * - **raw** {Boolean, default:false}, perform operations using raw bson buffers.
52 * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution.
53 * - **retryMiliSeconds** {Number, default:5000}, number of milliseconds between retries.
54 * - **numberOfRetries** {Number, default:5}, number of retries off connection.
55 * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**.
56 * - **slaveOk** {Number, default:null}, force setting of SlaveOk flag on queries (only use when explicitly connecting to a secondary server).
57 * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits
58 * - **bufferMaxEntries** {Boolean, default: -1}, sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited
59 *
60 * Deprecated Options
61 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
62 *
63 * @class Represents a Db
64 * @param {String} databaseName name of the database.
65 * @param {Object} serverConfig server config object.
66 * @param {Object} [options] additional options for the collection.
67 */
681function Db(databaseName, serverConfig, options) {
690 if(!(this instanceof Db)) return new Db(databaseName, serverConfig, options);
700 EventEmitter.call(this);
710 var self = this;
720 this.databaseName = databaseName;
730 this.serverConfig = serverConfig;
740 this.options = options == null ? {} : options;
75 // State to check against if the user force closed db
760 this._applicationClosed = false;
77 // Fetch the override flag if any
780 var overrideUsedFlag = this.options['override_used_flag'] == null ? false : this.options['override_used_flag'];
79
80 // Verify that nobody is using this config
810 if(!overrideUsedFlag && this.serverConfig != null && typeof this.serverConfig == 'object' && this.serverConfig._isUsed && this.serverConfig._isUsed()) {
820 throw new Error('A Server or ReplSet instance cannot be shared across multiple Db instances');
830 } else if(!overrideUsedFlag && typeof this.serverConfig == 'object'){
84 // Set being used
850 this.serverConfig._used = true;
86 }
87
88 // Allow slaveOk override
890 this.slaveOk = this.options['slave_ok'] == null ? false : this.options['slave_ok'];
900 this.slaveOk = this.options['slaveOk'] == null ? this.slaveOk : this.options['slaveOk'];
91
92 // Number of operations to buffer before failure
930 this.bufferMaxEntries = typeof this.options['bufferMaxEntries'] == 'number' ? this.options['bufferMaxEntries'] : -1;
94
95 // Ensure we have a valid db name
960 validateDatabaseName(databaseName);
97
98 // Contains all the connections for the db
990 try {
1000 this.native_parser = this.options.native_parser;
101 // The bson lib
1020 var bsonLib = this.bsonLib = this.options.native_parser ? require('bson').BSONNative : require('bson').BSONPure;
103 // Fetch the serializer object
1040 var BSON = bsonLib.BSON;
105
106 // Create a new instance
1070 this.bson = new BSON([bsonLib.Long, bsonLib.ObjectID, bsonLib.Binary, bsonLib.Code, bsonLib.DBRef, bsonLib.Symbol, bsonLib.Double, bsonLib.Timestamp, bsonLib.MaxKey, bsonLib.MinKey]);
1080 this.bson.promoteLongs = this.options.promoteLongs == null ? true : this.options.promoteLongs;
109
110 // Backward compatibility to access types
1110 this.bson_deserializer = bsonLib;
1120 this.bson_serializer = bsonLib;
113
114 // Add any overrides to the serializer and deserializer
1150 this.bson_deserializer.promoteLongs = this.options.promoteLongs == null ? true : this.options.promoteLongs;
116 } catch (err) {
117 // If we tried to instantiate the native driver
1180 var msg = 'Native bson parser not compiled, please compile '
119 + 'or avoid using native_parser=true';
1200 throw Error(msg);
121 }
122
123 // Internal state of the server
1240 this._state = 'disconnected';
125
1260 this.pkFactory = this.options.pk == null ? bsonLib.ObjectID : this.options.pk;
1270 this.forceServerObjectId = this.options.forceServerObjectId != null ? this.options.forceServerObjectId : false;
128
129 // Added safe
1300 this.safe = this.options.safe == null ? false : this.options.safe;
131
132 // If we have not specified a "safe mode" we just print a warning to the console
1330 if(this.options.safe == null && this.options.w == null && this.options.journal == null && this.options.fsync == null) {
1340 console.log("========================================================================================");
1350 console.log("= Please ensure that you set the default write concern for the database by setting =");
1360 console.log("= one of the options =");
1370 console.log("= =");
1380 console.log("= w: (value of > -1 or the string 'majority'), where < 1 means =");
1390 console.log("= no write acknowledgement =");
1400 console.log("= journal: true/false, wait for flush to journal before acknowledgement =");
1410 console.log("= fsync: true/false, wait for flush to file system before acknowledgement =");
1420 console.log("= =");
1430 console.log("= For backward compatibility safe is still supported and =");
1440 console.log("= allows values of [true | false | {j:true} | {w:n, wtimeout:n} | {fsync:true}] =");
1450 console.log("= the default value is false which means the driver receives does not =");
1460 console.log("= return the information of the success/error of the insert/update/remove =");
1470 console.log("= =");
1480 console.log("= ex: new Db(new Server('localhost', 27017), {safe:false}) =");
1490 console.log("= =");
1500 console.log("= http://www.mongodb.org/display/DOCS/getLastError+Command =");
1510 console.log("= =");
1520 console.log("= The default of no acknowledgement will change in the very near future =");
1530 console.log("= =");
1540 console.log("= This message will disappear when the default safe is set on the driver Db =");
1550 console.log("========================================================================================");
156 }
157
158 // Internal states variables
1590 this.notReplied ={};
1600 this.isInitializing = true;
1610 this.openCalled = false;
162
163 // Command queue, keeps a list of incoming commands that need to be executed once the connection is up
1640 this.commands = [];
165
166 // Set up logger
1670 this.logger = this.options.logger != null
168 && (typeof this.options.logger.debug == 'function')
169 && (typeof this.options.logger.error == 'function')
170 && (typeof this.options.logger.log == 'function')
171 ? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}};
172
173 // Associate the logger with the server config
1740 this.serverConfig.logger = this.logger;
1750 if(this.serverConfig.strategyInstance) this.serverConfig.strategyInstance.logger = this.logger;
1760 this.tag = new Date().getTime();
177 // Just keeps list of events we allow
1780 this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[]};
179
180 // Controls serialization options
1810 this.serializeFunctions = this.options.serializeFunctions != null ? this.options.serializeFunctions : false;
182
183 // Raw mode
1840 this.raw = this.options.raw != null ? this.options.raw : false;
185
186 // Record query stats
1870 this.recordQueryStats = this.options.recordQueryStats != null ? this.options.recordQueryStats : false;
188
189 // If we have server stats let's make sure the driver objects have it enabled
1900 if(this.recordQueryStats == true) {
1910 this.serverConfig.enableRecordQueryStats(true);
192 }
193
194 // Retry information
1950 this.retryMiliSeconds = this.options.retryMiliSeconds != null ? this.options.retryMiliSeconds : 1000;
1960 this.numberOfRetries = this.options.numberOfRetries != null ? this.options.numberOfRetries : 60;
197
198 // Set default read preference if any
1990 this.readPreference = this.options.readPreference;
200
201 // Set read preference on serverConfig if none is set
202 // but the db one was
2030 if(this.serverConfig.options.readPreference == null
204 && this.readPreference != null) {
2050 this.serverConfig.setReadPreference(this.readPreference);
206 }
207
208 // Ensure we keep a reference to this db
2090 this.serverConfig._dbStore.add(this);
210};
211
212/**
213 * @ignore
214 */
2151function validateDatabaseName(databaseName) {
2160 if(typeof databaseName !== 'string') throw new Error("database name must be a string");
2170 if(databaseName.length === 0) throw new Error("database name cannot be the empty string");
2180 if(databaseName == '$external') return;
219
2200 var invalidChars = [" ", ".", "$", "/", "\\"];
2210 for(var i = 0; i < invalidChars.length; i++) {
2220 if(databaseName.indexOf(invalidChars[i]) != -1) throw new Error("database names cannot contain the character '" + invalidChars[i] + "'");
223 }
224}
225
226/**
227 * @ignore
228 */
2291inherits(Db, EventEmitter);
230
231/**
232 * Initialize the database connection.
233 *
234 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the index information or null if an error occurred.
235 * @return {null}
236 * @api public
237 */
2381Db.prototype.open = function(callback) {
2390 var self = this;
240
241 // Check that the user has not called this twice
2420 if(this.openCalled) {
243 // Close db
2440 this.close();
245 // Throw error
2460 throw new Error("db object already connecting, open cannot be called multiple times");
247 }
248
249 // If we have a specified read preference
2500 if(this.readPreference != null) this.serverConfig.setReadPreference(this.readPreference);
251
252 // Set that db has been opened
2530 this.openCalled = true;
254
255 // Set the status of the server
2560 self._state = 'connecting';
257
258 // Set up connections
2590 if(self.serverConfig instanceof Server || self.serverConfig instanceof ReplSet || self.serverConfig instanceof Mongos) {
260 // Ensure we have the original options passed in for the server config
2610 var connect_options = {};
2620 for(var name in self.serverConfig.options) {
2630 connect_options[name] = self.serverConfig.options[name]
264 }
2650 connect_options.firstCall = true;
266
267 // Attempt to connect
2680 self.serverConfig.connect(self, connect_options, function(err, result) {
2690 if(err != null) {
270 // Close db to reset connection
2710 return self.close(function () {
272 // Return error from connection
2730 return callback(err, null);
274 });
275 }
276 // Set the status of the server
2770 self._state = 'connected';
278 // If we have queued up commands execute a command to trigger replays
2790 if(self.commands.length > 0) _execute_queued_command(self);
280 // Callback
2810 process.nextTick(function() {
2820 try {
2830 callback(null, self);
284 } catch(err) {
2850 self.close();
2860 throw err;
287 }
288 });
289 });
290 } else {
2910 try {
2920 callback(Error("Server parameter must be of type Server, ReplSet or Mongos"), null);
293 } catch(err) {
2940 self.close();
2950 throw err;
296 }
297 }
298};
299
300/**
301 * Create a new Db instance sharing the current socket connections.
302 *
303 * @param {String} dbName the name of the database we want to use.
304 * @return {Db} a db instance using the new database.
305 * @api public
306 */
3071Db.prototype.db = function(dbName) {
308 // Copy the options and add out internal override of the not shared flag
3090 var options = {};
3100 for(var key in this.options) {
3110 options[key] = this.options[key];
312 }
313
314 // Add override flag
3150 options['override_used_flag'] = true;
316 // Check if the db already exists and reuse if it's the case
3170 var db = this.serverConfig._dbStore.fetch(dbName);
318
319 // Create a new instance
3200 if(!db) {
3210 db = new Db(dbName, this.serverConfig, options);
322 }
323
324 // Return the db object
3250 return db;
326};
327
328/**
329 * Close the current db connection, including all the child db instances. Emits close event if no callback is provided.
330 *
331 * @param {Boolean} [forceClose] connection can never be reused.
332 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results or null if an error occurred.
333 * @return {null}
334 * @api public
335 */
3361Db.prototype.close = function(forceClose, callback) {
3370 var self = this;
338 // Ensure we force close all connections
3390 this._applicationClosed = false;
340
3410 if(typeof forceClose == 'function') {
3420 callback = forceClose;
3430 } else if(typeof forceClose == 'boolean') {
3440 this._applicationClosed = forceClose;
345 }
346
3470 this.serverConfig.close(function(err, result) {
348 // You can reuse the db as everything is shut down
3490 self.openCalled = false;
350 // If we have a callback call it
3510 if(callback) callback(err, result);
352 });
353};
354
355/**
356 * Access the Admin database
357 *
358 * @param {Function} [callback] returns the results.
359 * @return {Admin} the admin db object.
360 * @api public
361 */
3621Db.prototype.admin = function(callback) {
3630 if(callback == null) return new Admin(this);
3640 callback(null, new Admin(this));
365};
366
367/**
368 * Returns a cursor to all the collection information.
369 *
370 * @param {String} [collectionName] the collection name we wish to retrieve the information from.
371 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the options or null if an error occurred.
372 * @return {null}
373 * @api public
374 */
3751Db.prototype.collectionsInfo = function(collectionName, callback) {
3760 if(callback == null && typeof collectionName == 'function') { callback = collectionName; collectionName = null; }
377 // Create selector
3780 var selector = {};
379 // If we are limiting the access to a specific collection name
3800 if(collectionName != null) selector.name = this.databaseName + "." + collectionName;
381
382 // Return Cursor
383 // callback for backward compatibility
3840 if(callback) {
3850 callback(null, new Cursor(this, new Collection(this, DbCommand.SYSTEM_NAMESPACE_COLLECTION), selector));
386 } else {
3870 return new Cursor(this, new Collection(this, DbCommand.SYSTEM_NAMESPACE_COLLECTION), selector);
388 }
389};
390
391/**
392 * Get the list of all collection names for the specified db
393 *
394 * Options
395 * - **namesOnly** {String, default:false}, Return only the full collection namespace.
396 *
397 * @param {String} [collectionName] the collection name we wish to filter by.
398 * @param {Object} [options] additional options during update.
399 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collection names or null if an error occurred.
400 * @return {null}
401 * @api public
402 */
4031Db.prototype.collectionNames = function(collectionName, options, callback) {
4040 var self = this;
4050 var args = Array.prototype.slice.call(arguments, 0);
4060 callback = args.pop();
4070 collectionName = args.length ? args.shift() : null;
4080 options = args.length ? args.shift() || {} : {};
409
410 // Ensure no breaking behavior
4110 if(collectionName != null && typeof collectionName == 'object') {
4120 options = collectionName;
4130 collectionName = null;
414 }
415
416 // Let's make our own callback to reuse the existing collections info method
4170 self.collectionsInfo(collectionName, function(err, cursor) {
4180 if(err != null) return callback(err, null);
419
4200 cursor.toArray(function(err, documents) {
4210 if(err != null) return callback(err, null);
422
423 // List of result documents that have been filtered
4240 var filtered_documents = documents.filter(function(document) {
4250 return !(document.name.indexOf(self.databaseName) == -1 || document.name.indexOf('$') != -1);
426 });
427
428 // If we are returning only the names
4290 if(options.namesOnly) {
4300 filtered_documents = filtered_documents.map(function(document) { return document.name });
431 }
432
433 // Return filtered items
4340 callback(null, filtered_documents);
435 });
436 });
437};
438
439/**
440 * Fetch a specific collection (containing the actual collection information). If the application does not use strict mode you can
441 * can use it without a callback in the following way. var collection = db.collection('mycollection');
442 *
443 * Options
444* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
445 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
446 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
447 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
448 * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
449 * - **raw** {Boolean, default:false}, perform all operations using raw bson objects.
450 * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
451 * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
452 * - **strict**, (Boolean, default:false) returns an error if the collection does not exist
453 *
454 * Deprecated Options
455 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
456 *
457 * @param {String} collectionName the collection name we wish to access.
458 * @param {Object} [options] returns option results.
459 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collection or null if an error occurred.
460 * @return {null}
461 * @api public
462 */
4631Db.prototype.collection = function(collectionName, options, callback) {
4640 var self = this;
4650 if(typeof options === "function") { callback = options; options = {}; }
466 // Execute safe
467
4680 if(options && (options.strict)) {
4690 self.collectionNames(collectionName, function(err, collections) {
4700 if(err != null) return callback(err, null);
471
4720 if(collections.length == 0) {
4730 return callback(new Error("Collection " + collectionName + " does not exist. Currently in safe mode."), null);
474 } else {
4750 try {
4760 var collection = new Collection(self, collectionName, self.pkFactory, options);
477 } catch(err) {
4780 return callback(err, null);
479 }
4800 return callback(null, collection);
481 }
482 });
483 } else {
4840 try {
4850 var collection = new Collection(self, collectionName, self.pkFactory, options);
486 } catch(err) {
4870 if(callback == null) {
4880 throw err;
489 } else {
4900 return callback(err, null);
491 }
492 }
493
494 // If we have no callback return collection object
4950 return callback == null ? collection : callback(null, collection);
496 }
497};
498
499/**
500 * Fetch all collections for the current db.
501 *
502 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collections or null if an error occurred.
503 * @return {null}
504 * @api public
505 */
5061Db.prototype.collections = function(callback) {
5070 var self = this;
508 // Let's get the collection names
5090 self.collectionNames(function(err, documents) {
5100 if(err != null) return callback(err, null);
5110 var collections = [];
5120 documents.forEach(function(document) {
5130 collections.push(new Collection(self, document.name.replace(self.databaseName + ".", ''), self.pkFactory));
514 });
515 // Return the collection objects
5160 callback(null, collections);
517 });
518};
519
520/**
521 * Evaluate javascript on the server
522 *
523 * Options
524 * - **nolock** {Boolean, default:false}, Tell MongoDB not to block on the evaulation of the javascript.
525 *
526 * @param {Code} code javascript to execute on server.
527 * @param {Object|Array} [parameters] the parameters for the call.
528 * @param {Object} [options] the options
529 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from eval or null if an error occurred.
530 * @return {null}
531 * @api public
532 */
5331Db.prototype.eval = function(code, parameters, options, callback) {
534 // Unpack calls
5350 var args = Array.prototype.slice.call(arguments, 1);
5360 callback = args.pop();
5370 parameters = args.length ? args.shift() : parameters;
5380 options = args.length ? args.shift() || {} : {};
539
5400 var finalCode = code;
5410 var finalParameters = [];
542 // If not a code object translate to one
5430 if(!(finalCode instanceof this.bsonLib.Code)) {
5440 finalCode = new this.bsonLib.Code(finalCode);
545 }
546
547 // Ensure the parameters are correct
5480 if(parameters != null && parameters.constructor != Array && typeof parameters !== 'function') {
5490 finalParameters = [parameters];
5500 } else if(parameters != null && parameters.constructor == Array && typeof parameters !== 'function') {
5510 finalParameters = parameters;
552 }
553
554 // Create execution selector
5550 var selector = {'$eval':finalCode, 'args':finalParameters};
556 // Check if the nolock parameter is passed in
5570 if(options['nolock']) {
5580 selector['nolock'] = options['nolock'];
559 }
560
561 // Set primary read preference
5620 options.readPreference = ReadPreference.PRIMARY;
563
564 // Execute the eval
5650 this.collection(DbCommand.SYSTEM_COMMAND_COLLECTION).findOne(selector, options, function(err, result) {
5660 if(err) return callback(err);
567
5680 if(result && result.ok == 1) {
5690 callback(null, result.retval);
5700 } else if(result) {
5710 callback(new Error("eval failed: " + result.errmsg), null); return;
572 } else {
5730 callback(err, result);
574 }
575 });
576};
577
578/**
579 * Dereference a dbref, against a db
580 *
581 * @param {DBRef} dbRef db reference object we wish to resolve.
582 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dereference or null if an error occurred.
583 * @return {null}
584 * @api public
585 */
5861Db.prototype.dereference = function(dbRef, callback) {
5870 var db = this;
588 // If we have a db reference then let's get the db first
5890 if(dbRef.db != null) db = this.db(dbRef.db);
590 // Fetch the collection and find the reference
5910 var collection = db.collection(dbRef.namespace);
5920 collection.findOne({'_id':dbRef.oid}, function(err, result) {
5930 callback(err, result);
594 });
595};
596
597/**
598 * Logout user from server, fire off on all connections and remove all auth info
599 *
600 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from logout or null if an error occurred.
601 * @return {null}
602 * @api public
603 */
6041Db.prototype.logout = function(options, callback) {
6050 var self = this;
606 // Unpack calls
6070 var args = Array.prototype.slice.call(arguments, 0);
6080 callback = args.pop();
6090 options = args.length ? args.shift() || {} : {};
610
611 // Number of connections we need to logout from
6120 var numberOfConnections = this.serverConfig.allRawConnections().length;
613
614 // Let's generate the logout command object
6150 var logoutCommand = DbCommand.logoutCommand(self, {logout:1}, options);
6160 self._executeQueryCommand(logoutCommand, {onAll:true}, function(err, result) {
617 // Count down
6180 numberOfConnections = numberOfConnections - 1;
619 // Work around the case where the number of connections are 0
6200 if(numberOfConnections <= 0 && typeof callback == 'function') {
6210 var internalCallback = callback;
6220 callback = null;
623
624 // Remove the db from auths
6250 self.serverConfig.auth.remove(self.databaseName);
626
627 // Handle error result
6280 utils.handleSingleCommandResultReturn(true, false, internalCallback)(err, result);
629 }
630 });
631};
632
633/**
634 * Authenticate a user against the server.
635 * authMechanism
636 * Options
637 * - **authMechanism** {String, default:MONGODB-CR}, The authentication mechanism to use, GSSAPI or MONGODB-CR
638 *
639 * @param {String} username username.
640 * @param {String} password password.
641 * @param {Object} [options] the options
642 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from authentication or null if an error occurred.
643 * @return {null}
644 * @api public
645 */
6461Db.prototype.authenticate = function(username, password, options, callback) {
6470 var self = this;
648
6490 if(typeof options == 'function') {
6500 callback = options;
6510 options = {};
652 }
653
654 // Set default mechanism
6550 if(!options.authMechanism) {
6560 options.authMechanism = 'MONGODB-CR';
6570 } else if(options.authMechanism != 'GSSAPI'
658 && options.authMechanism != 'MONGODB-CR'
659 && options.authMechanism != 'MONGODB-X509'
660 && options.authMechanism != 'PLAIN') {
6610 return callback(new Error("only GSSAPI, PLAIN, MONGODB-X509 or MONGODB-CR is supported by authMechanism"));
662 }
663
664 // the default db to authenticate against is 'this'
665 // if authententicate is called from a retry context, it may be another one, like admin
6660 var authdb = options.authdb ? options.authdb : self.databaseName;
6670 authdb = options.authSource ? options.authSource : authdb;
668
669 // Callback
6700 var _callback = function(err, result) {
6710 if(self.listeners("authenticated").length > 9) {
6720 self.emit("authenticated", err, result);
673 }
674
675 // Return to caller
6760 callback(err, result);
677 }
678
679 // If classic auth delegate to auth command
6800 if(options.authMechanism == 'MONGODB-CR') {
6810 mongodb_cr_authenticate(self, username, password, authdb, options, _callback);
6820 } else if(options.authMechanism == 'PLAIN') {
6830 mongodb_plain_authenticate(self, username, password, options, _callback);
6840 } else if(options.authMechanism == 'MONGODB-X509') {
6850 mongodb_x509_authenticate(self, username, password, options, _callback);
6860 } else if(options.authMechanism == 'GSSAPI') {
687 //
688 // Kerberos library is not installed, throw and error
6890 if(hasKerberos == false) {
6900 console.log("========================================================================================");
6910 console.log("= Please make sure that you install the Kerberos library to use GSSAPI =");
6920 console.log("= =");
6930 console.log("= npm install -g kerberos =");
6940 console.log("= =");
6950 console.log("= The Kerberos package is not installed by default for simplicities sake =");
6960 console.log("= and needs to be global install =");
6970 console.log("========================================================================================");
6980 throw new Error("Kerberos library not installed");
699 }
700
7010 if(process.platform == 'win32') {
7020 mongodb_sspi_authenticate(self, username, password, authdb, options, _callback);
703 } else {
704 // We have the kerberos library, execute auth process
7050 mongodb_gssapi_authenticate(self, username, password, authdb, options, _callback);
706 }
707 }
708};
709
710/**
711 * Add a user to the database.
712 *
713 * Options
714 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
715 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
716 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
717 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
718 * - **customData**, (Object, default:{}) custom data associated with the user (only Mongodb 2.6 or higher)
719 * - **roles**, (Array, default:[]) roles associated with the created user (only Mongodb 2.6 or higher)
720 *
721 * Deprecated Options
722 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
723 *
724 * @param {String} username username.
725 * @param {String} password password.
726 * @param {Object} [options] additional options during update.
727 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from addUser or null if an error occurred.
728 * @return {null}
729 * @api public
730 */
7311Db.prototype.addUser = function(username, password, options, callback) {
732 // Checkout a write connection to get the server capabilities
7330 var connection = this.serverConfig.checkoutWriter();
7340 if(connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasAuthCommands) {
7350 return _executeAuthCreateUserCommand(this, username, password, options, callback);
736 }
737
738 // Unpack the parameters
7390 var self = this;
7400 var args = Array.prototype.slice.call(arguments, 2);
7410 callback = args.pop();
7420 options = args.length ? args.shift() || {} : {};
743
744 // Get the error options
7450 var errorOptions = _getWriteConcern(this, options);
7460 errorOptions.w = errorOptions.w == null ? 1 : errorOptions.w;
747 // Use node md5 generator
7480 var md5 = crypto.createHash('md5');
749 // Generate keys used for authentication
7500 md5.update(username + ":mongo:" + password);
7510 var userPassword = md5.digest('hex');
752 // Fetch a user collection
7530 var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION);
754 // Check if we are inserting the first user
7550 collection.count({}, function(err, count) {
756 // We got an error (f.ex not authorized)
7570 if(err != null) return callback(err, null);
758 // Check if the user exists and update i
7590 collection.find({user: username}, {dbName: options['dbName']}).toArray(function(err, documents) {
760 // We got an error (f.ex not authorized)
7610 if(err != null) return callback(err, null);
762 // Add command keys
7630 var commandOptions = errorOptions;
7640 commandOptions.dbName = options['dbName'];
7650 commandOptions.upsert = true;
766
767 // We have a user, let's update the password or upsert if not
7680 collection.update({user: username},{$set: {user: username, pwd: userPassword}}, commandOptions, function(err, results, full) {
7690 if(count == 0 && err) {
7700 callback(null, [{user:username, pwd:userPassword}]);
7710 } else if(err) {
7720 callback(err, null)
773 } else {
7740 callback(null, [{user:username, pwd:userPassword}]);
775 }
776 });
777 });
778 });
779};
780
781/**
782 * @ignore
783 */
7841var _executeAuthCreateUserCommand = function(self, username, password, options, callback) {
785 // Special case where there is no password ($external users)
7860 if(typeof username == 'string'
787 && password != null && typeof password == 'object') {
7880 callback = options;
7890 options = password;
7900 password = null;
791 }
792
793 // Unpack all options
7940 if(typeof options == 'function') {
7950 callback = options;
7960 options = {};
797 }
798
799 // Error out if we digestPassword set
8000 if(options.digestPassword != null) {
8010 throw utils.toError("The digestPassword option is not supported via add_user. Please use db.command('createUser', ...) instead for this option.");
802 }
803
804 // Get additional values
8050 var customData = options.customData != null ? options.customData : {};
8060 var roles = Array.isArray(options.roles) ? options.roles : [];
8070 var maxTimeMS = typeof options.maxTimeMS == 'number' ? options.maxTimeMS : null;
808
809 // If not roles defined print deprecated message
8100 if(roles.length == 0) {
8110 console.log("Creating a user without roles is deprecated in MongoDB >= 2.6");
812 }
813
814 // Get the error options
8150 var writeConcern = _getWriteConcern(self, options);
8160 var commandOptions = {writeCommand:true};
8170 if(options['dbName']) commandOptions.dbName = options['dbName'];
818
819 // Add maxTimeMS to options if set
8200 if(maxTimeMS != null) commandOptions.maxTimeMS = maxTimeMS;
821
822 // Check the db name and add roles if needed
8230 if((self.databaseName.toLowerCase() == 'admin' || options.dbName == 'admin') && !Array.isArray(options.roles)) {
8240 roles = ['root']
8250 } else if(!Array.isArray(options.roles)) {
8260 roles = ['dbOwner']
827 }
828
829 // Build the command to execute
8300 var command = {
831 createUser: username
832 , customData: customData
833 , roles: roles
834 , digestPassword:false
835 , writeConcern: writeConcern
836 }
837
838 // Use node md5 generator
8390 var md5 = crypto.createHash('md5');
840 // Generate keys used for authentication
8410 md5.update(username + ":mongo:" + password);
8420 var userPassword = md5.digest('hex');
843
844 // No password
8450 if(typeof password == 'string') {
8460 command.pwd = userPassword;
847 }
848
849 // console.log("================================== add user")
850 // console.dir(command)
851
852 // Execute the command
8530 self.command(command, commandOptions, function(err, result) {
8540 if(err) return callback(err, null);
8550 callback(!result.ok ? utils.toError("Failed to add user " + username) : null
856 , result.ok ? [{user: username, pwd: ''}] : null);
857 })
858}
859
860/**
861 * Remove a user from a database
862 *
863 * Options
864 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
865 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
866 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
867 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
868 *
869 * Deprecated Options
870 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
871 *
872 * @param {String} username username.
873 * @param {Object} [options] additional options during update.
874 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occurred.
875 * @return {null}
876 * @api public
877 */
8781Db.prototype.removeUser = function(username, options, callback) {
879 // Checkout a write connection to get the server capabilities
8800 var connection = this.serverConfig.checkoutWriter();
8810 if(connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasAuthCommands) {
8820 return _executeAuthRemoveUserCommand(this, username, options, callback);
883 }
884
885 // Unpack the parameters
8860 var self = this;
8870 var args = Array.prototype.slice.call(arguments, 1);
8880 callback = args.pop();
8890 options = args.length ? args.shift() || {} : {};
890
891 // Figure out the safe mode settings
8920 var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe;
893 // Override with options passed in if applicable
8940 safe = options != null && options['safe'] != null ? options['safe'] : safe;
895 // Ensure it's at least set to safe
8960 safe = safe == null ? {w: 1} : safe;
897
898 // Fetch a user collection
8990 var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION);
9000 collection.findOne({user: username}, {dbName: options['dbName']}, function(err, user) {
9010 if(user != null) {
902 // Add command keys
9030 var commandOptions = safe;
9040 commandOptions.dbName = options['dbName'];
905
9060 collection.remove({user: username}, commandOptions, function(err, result) {
9070 callback(err, true);
908 });
909 } else {
9100 callback(err, false);
911 }
912 });
913};
914
9151var _executeAuthRemoveUserCommand = function(self, username, options, callback) {
916 // Unpack all options
9170 if(typeof options == 'function') {
9180 callback = options;
9190 options = {};
920 }
921
922 // Get the error options
9230 var writeConcern = _getWriteConcern(self, options);
9240 var commandOptions = {writeCommand:true};
9250 if(options['dbName']) commandOptions.dbName = options['dbName'];
926
927 // Get additional values
9280 var maxTimeMS = typeof options.maxTimeMS == 'number' ? options.maxTimeMS : null;
929
930 // Add maxTimeMS to options if set
9310 if(maxTimeMS != null) commandOptions.maxTimeMS = maxTimeMS;
932
933 // Build the command to execute
9340 var command = {
935 dropUser: username
936 , writeConcern: writeConcern
937 }
938
939 // Execute the command
9400 self.command(command, commandOptions, function(err, result) {
9410 if(err) return callback(err, null);
9420 callback(null, result.ok ? true : false);
943 })
944}
945
946/**
947 * Creates a collection on a server pre-allocating space, need to create f.ex capped collections.
948 *
949 * Options
950* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
951 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
952 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
953 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
954 * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
955 * - **raw** {Boolean, default:false}, perform all operations using raw bson objects.
956 * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
957 * - **capped** {Boolean, default:false}, create a capped collection.
958 * - **size** {Number}, the size of the capped collection in bytes.
959 * - **max** {Number}, the maximum number of documents in the capped collection.
960 * - **autoIndexId** {Boolean, default:true}, create an index on the _id field of the document, True by default on MongoDB 2.2 or higher off for version < 2.2.
961 * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
962 * - **strict**, (Boolean, default:false) throws an error if collection already exists
963 *
964 * Deprecated Options
965 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
966 *
967 * @param {String} collectionName the collection name we wish to access.
968 * @param {Object} [options] returns option results.
969 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from createCollection or null if an error occurred.
970 * @return {null}
971 * @api public
972 */
9731Db.prototype.createCollection = function(collectionName, options, callback) {
9740 var self = this;
9750 if(typeof options == 'function') {
9760 callback = options;
9770 options = {};
978 }
979
980 // Figure out the safe mode settings
9810 var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe;
982 // Override with options passed in if applicable
9830 safe = options != null && options['safe'] != null ? options['safe'] : safe;
984 // Ensure it's at least set to safe
9850 safe = safe == null ? {w: 1} : safe;
986
987 // Check if we have the name
9880 this.collectionNames(collectionName, function(err, collections) {
9890 if(err != null) return callback(err, null);
990
9910 var found = false;
9920 collections.forEach(function(collection) {
9930 if(collection.name == self.databaseName + "." + collectionName) found = true;
994 });
995
996 // If the collection exists either throw an exception (if db in safe mode) or return the existing collection
9970 if(found && options && options.strict) {
9980 return callback(new Error("Collection " + collectionName + " already exists. Currently in safe mode."), null);
9990 } else if(found){
10000 try {
10010 var collection = new Collection(self, collectionName, self.pkFactory, options);
1002 } catch(err) {
10030 return callback(err, null);
1004 }
10050 return callback(null, collection);
1006 }
1007
1008 // Create a new collection and return it
10090 self._executeQueryCommand(DbCommand.createCreateCollectionCommand(self, collectionName, options)
1010 , {read:false, safe:safe}
1011 , utils.handleSingleCommandResultReturn(null, null, function(err, result) {
10120 if(err) return callback(err, null);
1013 // Create collection and return
10140 try {
10150 return callback(null, new Collection(self, collectionName, self.pkFactory, options));
1016 } catch(err) {
10170 return callback(err, null);
1018 }
1019 }));
1020 });
1021};
1022
10231var _getReadConcern = function(self, options) {
10240 if(options.readPreference) return options.readPreference;
10250 if(self.readPreference) return self.readPreference;
10260 return 'primary';
1027}
1028
1029/**
1030 * Execute a command hash against MongoDB. This lets you acess any commands not available through the api on the server.
1031 *
1032 * Options
1033 * - **maxTimeMS** {Number}, number of miliseconds to wait before aborting the query.
1034 * - **ignoreCommandFilter** {Boolean}, overrides the default redirection of certain commands to primary.
1035 * - **writeCommand** {Boolean, default: false}, signals this is a write command and to ignore read preferences
1036 * - **checkKeys** {Boolean, default: false}, overrides the default not to check the key names for the command
1037 *
1038 * @param {Object} selector the command hash to send to the server, ex: {ping:1}.
1039 * @param {Object} [options] additional options for the command.
1040 * @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter.
1041 * @return {null}
1042 * @api public
1043 */
10441Db.prototype.command = function(selector, options, callback) {
10450 if(typeof options == 'function') {
10460 callback = options;
10470 options = {};
1048 }
1049
1050 // Ignore command preference (I know what I'm doing)
10510 var ignoreCommandFilter = options.ignoreCommandFilter ? options.ignoreCommandFilter : false;
1052 // Set read preference if we set one
10530 var readPreference = _getReadConcern(this, options);
1054
1055 // Ensure only commands who support read Prefrences are exeuted otherwise override and use Primary
10560 if(readPreference != false && ignoreCommandFilter == false) {
10570 if(selector['group'] || selector['aggregate'] || selector['collStats'] || selector['dbStats']
1058 || selector['count'] || selector['distinct'] || selector['geoNear'] || selector['geoSearch']
1059 || selector['geoWalk'] || selector['text']
1060 || (selector['mapreduce'] && (selector.out == 'inline' || selector.out.inline))) {
1061 // Set the read preference
10620 options.readPreference = readPreference;
1063 } else {
10640 options.readPreference = ReadPreference.PRIMARY;
1065 }
10660 } else if(readPreference != false) {
10670 options.readPreference = readPreference;
1068 }
1069
1070 // Add the maxTimeMS option to the command if specified
10710 if(typeof options.maxTimeMS == 'number') {
10720 selector.maxTimeMS = options.maxTimeMS
1073 }
1074
1075 // Command options
10760 var command_options = {};
1077
1078 // Do we have an override for checkKeys
10790 if(typeof options['checkKeys'] == 'boolean') command_options['checkKeys'] = options['checkKeys'];
10800 command_options['checkKeys'] = typeof options['checkKeys'] == 'boolean' ? options['checkKeys'] : false;
10810 if(typeof options['serializeFunctions'] == 'boolean') command_options['serializeFunctions'] = options['serializeFunctions'];
10820 if(options['dbName']) command_options['dbName'] = options['dbName'];
1083
1084 // If we have a write command, remove readPreference as an option
10850 if((options.writeCommand
1086 || selector['findAndModify']
1087 || selector['insert'] || selector['update'] || selector['delete']
1088 || selector['createUser'] || selector['updateUser'] || selector['removeUser'])
1089 && options.readPreference) {
10900 delete options['readPreference'];
1091 }
1092
1093 // Execute a query command
10940 this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, selector, command_options), options, function(err, results) {
10950 if(err) return callback(err, null);
10960 if(results.documents[0].errmsg)
10970 return callback(utils.toError(results.documents[0]), null);
10980 callback(null, results.documents[0]);
1099 });
1100};
1101
1102/**
1103 * Drop a collection from the database, removing it permanently. New accesses will create a new collection.
1104 *
1105 * @param {String} collectionName the name of the collection we wish to drop.
1106 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropCollection or null if an error occurred.
1107 * @return {null}
1108 * @api public
1109 */
11101Db.prototype.dropCollection = function(collectionName, callback) {
11110 var self = this;
11120 callback || (callback = function(){});
1113
1114 // Drop the collection
11150 this._executeQueryCommand(DbCommand.createDropCollectionCommand(this, collectionName)
1116 , utils.handleSingleCommandResultReturn(true, false, callback)
1117 );
1118};
1119
1120/**
1121 * Rename a collection.
1122 *
1123 * Options
1124 * - **dropTarget** {Boolean, default:false}, drop the target name collection if it previously exists.
1125 *
1126 * @param {String} fromCollection the name of the current collection we wish to rename.
1127 * @param {String} toCollection the new name of the collection.
1128 * @param {Object} [options] returns option results.
1129 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from renameCollection or null if an error occurred.
1130 * @return {null}
1131 * @api public
1132 */
11331Db.prototype.renameCollection = function(fromCollection, toCollection, options, callback) {
11340 var self = this;
1135
11360 if(typeof options == 'function') {
11370 callback = options;
11380 options = {}
1139 }
1140
1141 // Add return new collection
11420 options.new_collection = true;
1143
1144 // Execute using the collection method
11450 this.collection(fromCollection).rename(toCollection, options, callback);
1146};
1147
1148/**
1149 * Return last error message for the given connection, note options can be combined.
1150 *
1151 * Options
1152 * - **fsync** {Boolean, default:false}, option forces the database to fsync all files before returning.
1153 * - **j** {Boolean, default:false}, awaits the journal commit before returning, > MongoDB 2.0.
1154 * - **w** {Number}, until a write operation has been replicated to N servers.
1155 * - **wtimeout** {Number}, number of miliseconds to wait before timing out.
1156 *
1157 * Connection Options
1158 * - **connection** {Connection}, fire the getLastError down a specific connection.
1159 *
1160 * @param {Object} [options] returns option results.
1161 * @param {Object} [connectionOptions] returns option results.
1162 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from lastError or null if an error occurred.
1163 * @return {null}
1164 * @api public
1165 */
11661Db.prototype.lastError = function(options, connectionOptions, callback) {
1167 // Unpack calls
11680 var args = Array.prototype.slice.call(arguments, 0);
11690 callback = args.pop();
11700 options = args.length ? args.shift() || {} : {};
11710 connectionOptions = args.length ? args.shift() || {} : {};
1172
11730 this._executeQueryCommand(DbCommand.createGetLastErrorCommand(options, this), connectionOptions, function(err, error) {
11740 callback(err, error && error.documents);
1175 });
1176};
1177
1178/**
1179 * Legacy method calls.
1180 *
1181 * @ignore
1182 * @api private
1183 */
11841Db.prototype.error = Db.prototype.lastError;
11851Db.prototype.lastStatus = Db.prototype.lastError;
1186
1187/**
1188 * Return all errors up to the last time db reset_error_history was called.
1189 *
1190 * Options
1191 * - **connection** {Connection}, fire the getLastError down a specific connection.
1192 *
1193 * @param {Object} [options] returns option results.
1194 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from previousErrors or null if an error occurred.
1195 * @return {null}
1196 * @api public
1197 */
11981Db.prototype.previousErrors = function(options, callback) {
1199 // Unpack calls
12000 var args = Array.prototype.slice.call(arguments, 0);
12010 callback = args.pop();
12020 options = args.length ? args.shift() || {} : {};
1203
12040 this._executeQueryCommand(DbCommand.createGetPreviousErrorsCommand(this), options, function(err, error) {
12050 callback(err, error.documents);
1206 });
1207};
1208
1209/**
1210 * Runs a command on the database.
1211 * @ignore
1212 * @api private
1213 */
12141Db.prototype.executeDbCommand = function(command_hash, options, callback) {
12150 if(callback == null) { callback = options; options = {}; }
12160 this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, command_hash, options), options, function(err, result) {
12170 if(callback) callback(err, result);
1218 });
1219};
1220
1221/**
1222 * Runs a command on the database as admin.
1223 * @ignore
1224 * @api private
1225 */
12261Db.prototype.executeDbAdminCommand = function(command_hash, options, callback) {
12270 if(typeof options == 'function') {
12280 callback = options;
12290 options = {}
1230 }
1231
12320 if(options.readPreference) {
12330 options.read = options.readPreference;
1234 }
1235
12360 this._executeQueryCommand(DbCommand.createAdminDbCommand(this, command_hash), options, function(err, result) {
12370 if(callback) callback(err, result);
1238 });
1239};
1240
1241/**
1242 * Resets the error history of the mongo instance.
1243 *
1244 * Options
1245 * - **connection** {Connection}, fire the getLastError down a specific connection.
1246 *
1247 * @param {Object} [options] returns option results.
1248 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from resetErrorHistory or null if an error occurred.
1249 * @return {null}
1250 * @api public
1251 */
12521Db.prototype.resetErrorHistory = function(options, callback) {
1253 // Unpack calls
12540 var args = Array.prototype.slice.call(arguments, 0);
12550 callback = args.pop();
12560 options = args.length ? args.shift() || {} : {};
1257
12580 this._executeQueryCommand(DbCommand.createResetErrorHistoryCommand(this), options, function(err, error) {
12590 if(callback) callback(err, error && error.documents);
1260 });
1261};
1262
1263/**
1264 * Creates an index on the collection.
1265 *
1266 * Options
1267* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
1268 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
1269 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
1270 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
1271 * - **unique** {Boolean, default:false}, creates an unique index.
1272 * - **sparse** {Boolean, default:false}, creates a sparse index.
1273 * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible.
1274 * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value
1275 * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates.
1276 * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates.
1277 * - **v** {Number}, specify the format version of the indexes.
1278 * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
1279 * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
1280 *
1281 * Deprecated Options
1282 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
1283 *
1284 *
1285 * @param {String} collectionName name of the collection to create the index on.
1286 * @param {Object} fieldOrSpec fieldOrSpec that defines the index.
1287 * @param {Object} [options] additional options during update.
1288 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from createIndex or null if an error occurred.
1289 * @return {null}
1290 * @api public
1291 */
12921Db.prototype.createIndex = function(collectionName, fieldOrSpec, options, callback) {
12930 var self = this;
12940 var args = Array.prototype.slice.call(arguments, 2);
12950 callback = args.pop();
12960 options = args.length ? args.shift() || {} : {};
12970 options = typeof callback === 'function' ? options : callback;
12980 options = options == null ? {} : options;
1299
1300 // Get the error options
13010 var errorOptions = _getWriteConcern(this, options);
1302 // Create command
13030 var command = DbCommand.createCreateIndexCommand(this, collectionName, fieldOrSpec, options);
1304 // Default command options
13050 var commandOptions = {};
1306
1307 // If we have error conditions set handle them
13080 if(_hasWriteConcern(errorOptions) && typeof callback == 'function') {
1309 // Insert options
13100 commandOptions['read'] = false;
1311 // If we have safe set set async to false
13120 if(errorOptions == null) commandOptions['async'] = true;
1313
1314 // Set safe option
13150 commandOptions['safe'] = errorOptions;
1316 // If we have an error option
13170 if(typeof errorOptions == 'object') {
13180 var keys = Object.keys(errorOptions);
13190 for(var i = 0; i < keys.length; i++) {
13200 commandOptions[keys[i]] = errorOptions[keys[i]];
1321 }
1322 }
1323
1324 // Execute insert command
13250 this._executeInsertCommand(command, commandOptions, function(err, result) {
13260 if(err != null) return callback(err, null);
1327
13280 result = result && result.documents;
13290 if (result[0].err) {
13300 callback(utils.toError(result[0]));
1331 } else {
13320 callback(null, command.documents[0].name);
1333 }
1334 });
13350 } else if(_hasWriteConcern(errorOptions) && callback == null) {
13360 throw new Error("Cannot use a writeConcern without a provided callback");
1337 } else {
1338 // Execute insert command
13390 var result = this._executeInsertCommand(command, commandOptions);
1340 // If no callback just return
13410 if(!callback) return;
1342 // If error return error
13430 if(result instanceof Error) {
13440 return callback(result);
1345 }
1346 // Otherwise just return
13470 return callback(null, null);
1348 }
1349};
1350
1351/**
1352 * Ensures that an index exists, if it does not it creates it
1353 *
1354 * Options
1355 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
1356 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
1357 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
1358 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
1359 * - **unique** {Boolean, default:false}, creates an unique index.
1360 * - **sparse** {Boolean, default:false}, creates a sparse index.
1361 * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible.
1362 * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value
1363 * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates.
1364 * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates.
1365 * - **v** {Number}, specify the format version of the indexes.
1366 * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
1367 * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
1368 *
1369 * Deprecated Options
1370 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
1371 *
1372 * @param {String} collectionName name of the collection to create the index on.
1373 * @param {Object} fieldOrSpec fieldOrSpec that defines the index.
1374 * @param {Object} [options] additional options during update.
1375 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from ensureIndex or null if an error occurred.
1376 * @return {null}
1377 * @api public
1378 */
13791Db.prototype.ensureIndex = function(collectionName, fieldOrSpec, options, callback) {
13800 var self = this;
1381
13820 if (typeof callback === 'undefined' && typeof options === 'function') {
13830 callback = options;
13840 options = {};
1385 }
1386
13870 if (options == null) {
13880 options = {};
1389 }
1390
1391 // Get the error options
13920 var errorOptions = _getWriteConcern(this, options);
1393 // Make sure we don't try to do a write concern without a callback
13940 if(_hasWriteConcern(errorOptions) && callback == null)
13950 throw new Error("Cannot use a writeConcern without a provided callback");
1396 // Create command
13970 var command = DbCommand.createCreateIndexCommand(this, collectionName, fieldOrSpec, options);
13980 var index_name = command.documents[0].name;
1399
1400 // Default command options
14010 var commandOptions = {};
1402 // Check if the index allready exists
14030 this.indexInformation(collectionName, function(err, collectionInfo) {
14040 if(err != null) return callback(err, null);
1405
14060 if(!collectionInfo[index_name]) {
1407 // If we have error conditions set handle them
14080 if(_hasWriteConcern(errorOptions) && typeof callback == 'function') {
1409 // Insert options
14100 commandOptions['read'] = false;
1411 // If we have safe set set async to false
14120 if(errorOptions == null) commandOptions['async'] = true;
1413
1414 // If we have an error option
14150 if(typeof errorOptions == 'object') {
14160 var keys = Object.keys(errorOptions);
14170 for(var i = 0; i < keys.length; i++) {
14180 commandOptions[keys[i]] = errorOptions[keys[i]];
1419 }
1420 }
1421
14220 if(typeof callback === 'function'
1423 && commandOptions.w < 1 && !commandOptions.fsync && !commandOptions.journal) {
14240 commandOptions.w = 1;
1425 }
1426
14270 self._executeInsertCommand(command, commandOptions, function(err, result) {
1428 // Only callback if we have one specified
14290 if(typeof callback === 'function') {
14300 if(err != null) return callback(err, null);
1431
14320 result = result && result.documents;
14330 if (result[0].err) {
14340 callback(utils.toError(result[0]));
1435 } else {
14360 callback(null, command.documents[0].name);
1437 }
1438 }
1439 });
1440 } else {
1441 // Execute insert command
14420 var result = self._executeInsertCommand(command, commandOptions);
1443 // If no callback just return
14440 if(!callback) return;
1445 // If error return error
14460 if(result instanceof Error) {
14470 return callback(result);
1448 }
1449 // Otherwise just return
14500 return callback(null, index_name);
1451 }
1452 } else {
14530 if(typeof callback === 'function') return callback(null, index_name);
1454 }
1455 });
1456};
1457
1458/**
1459 * Returns the information available on allocated cursors.
1460 *
1461 * Options
1462 * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
1463 *
1464 * @param {Object} [options] additional options during update.
1465 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from cursorInfo or null if an error occurred.
1466 * @return {null}
1467 * @api public
1468 */
14691Db.prototype.cursorInfo = function(options, callback) {
14700 var args = Array.prototype.slice.call(arguments, 0);
14710 callback = args.pop();
14720 options = args.length ? args.shift() || {} : {};
1473
14740 this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, {'cursorInfo':1})
1475 , options
1476 , utils.handleSingleCommandResultReturn(null, null, callback));
1477};
1478
1479/**
1480 * Drop an index on a collection.
1481 *
1482 * @param {String} collectionName the name of the collection where the command will drop an index.
1483 * @param {String} indexName name of the index to drop.
1484 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropIndex or null if an error occurred.
1485 * @return {null}
1486 * @api public
1487 */
14881Db.prototype.dropIndex = function(collectionName, indexName, callback) {
14890 this._executeQueryCommand(DbCommand.createDropIndexCommand(this, collectionName, indexName)
1490 , utils.handleSingleCommandResultReturn(null, null, callback));
1491};
1492
1493/**
1494 * Reindex all indexes on the collection
1495 * Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections.
1496 *
1497 * @param {String} collectionName the name of the collection.
1498 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from reIndex or null if an error occurred.
1499 * @api public
1500**/
15011Db.prototype.reIndex = function(collectionName, callback) {
15020 this._executeQueryCommand(DbCommand.createReIndexCommand(this, collectionName)
1503 , utils.handleSingleCommandResultReturn(true, false, callback));
1504};
1505
1506/**
1507 * Retrieves this collections index info.
1508 *
1509 * Options
1510 * - **full** {Boolean, default:false}, returns the full raw index information.
1511 * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST).
1512 *
1513 * @param {String} collectionName the name of the collection.
1514 * @param {Object} [options] additional options during update.
1515 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from indexInformation or null if an error occurred.
1516 * @return {null}
1517 * @api public
1518 */
15191Db.prototype.indexInformation = function(collectionName, options, callback) {
15200 if(typeof callback === 'undefined') {
15210 if(typeof options === 'undefined') {
15220 callback = collectionName;
15230 collectionName = null;
1524 } else {
15250 callback = options;
1526 }
15270 options = {};
1528 }
1529
1530 // If we specified full information
15310 var full = options['full'] == null ? false : options['full'];
1532 // Build selector for the indexes
15330 var selector = collectionName != null ? {ns: (this.databaseName + "." + collectionName)} : {};
1534
1535 // Set read preference if we set one
15360 var readPreference = options['readPreference'] ? options['readPreference'] : ReadPreference.PRIMARY;
1537
1538 // Iterate through all the fields of the index
15390 this.collection(DbCommand.SYSTEM_INDEX_COLLECTION, function(err, collection) {
1540 // Perform the find for the collection
15410 collection.find(selector).setReadPreference(readPreference).toArray(function(err, indexes) {
15420 if(err != null) return callback(err, null);
1543 // Contains all the information
15440 var info = {};
1545
1546 // if full defined just return all the indexes directly
15470 if(full) return callback(null, indexes);
1548
1549 // Process all the indexes
15500 for(var i = 0; i < indexes.length; i++) {
15510 var index = indexes[i];
1552 // Let's unpack the object
15530 info[index.name] = [];
15540 for(var name in index.key) {
15550 info[index.name].push([name, index.key[name]]);
1556 }
1557 }
1558
1559 // Return all the indexes
15600 callback(null, info);
1561 });
1562 });
1563};
1564
1565/**
1566 * Drop a database.
1567 *
1568 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropDatabase or null if an error occurred.
1569 * @return {null}
1570 * @api public
1571 */
15721Db.prototype.dropDatabase = function(callback) {
15730 this._executeQueryCommand(DbCommand.createDropDatabaseCommand(this)
1574 , utils.handleSingleCommandResultReturn(true, false, callback));
1575}
1576
1577/**
1578 * Get all the db statistics.
1579 *
1580 * Options
1581 * - **scale** {Number}, divide the returned sizes by scale value.
1582 * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST).
1583 *
1584 * @param {Objects} [options] options for the stats command
1585 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from stats or null if an error occurred.
1586 * @return {null}
1587 * @api public
1588 */
15891Db.prototype.stats = function stats(options, callback) {
15900 var args = Array.prototype.slice.call(arguments, 0);
15910 callback = args.pop();
1592 // Fetch all commands
15930 options = args.length ? args.shift() || {} : {};
1594
1595 // Build command object
15960 var commandObject = {
1597 dbStats:this.collectionName
1598 };
1599
1600 // Check if we have the scale value
16010 if(options['scale'] != null) commandObject['scale'] = options['scale'];
1602
1603 // Execute the command
16040 this.command(commandObject, options, callback);
1605}
1606
1607/**
1608 * @ignore
1609 */
16101var __executeQueryCommand = function(self, db_command, options, callback) {
1611 // Options unpacking
16120 var read = options['read'] != null ? options['read'] : false;
16130 read = options['readPreference'] != null && options['read'] == null ? options['readPreference'] : read;
16140 var raw = options['raw'] != null ? options['raw'] : self.raw;
16150 var onAll = options['onAll'] != null ? options['onAll'] : false;
16160 var specifiedConnection = options['connection'] != null ? options['connection'] : null;
1617
1618 // Correct read preference to default primary if set to false, null or primary
16190 if(!(typeof read == 'object') && read._type == 'ReadPreference') {
16200 read = (read == null || read == 'primary' || read == false) ? ReadPreference.PRIMARY : read;
16210 if(!ReadPreference.isValid(read)) return callback(new Error("Illegal readPreference mode specified, " + read));
16220 } else if(typeof read == 'object' && read._type == 'ReadPreference') {
16230 if(!read.isValid()) return callback(new Error("Illegal readPreference mode specified, " + read.mode));
1624 }
1625
1626 // If we have a read preference set and we are a mongos pass the read preference on to the mongos instance,
16270 if(self.serverConfig.isMongos() && read != null && read != false) {
16280 db_command.setMongosReadPreference(read);
1629 }
1630
1631 // If we got a callback object
16320 if(typeof callback === 'function' && !onAll) {
1633 // Override connection if we passed in a specific connection
16340 var connection = specifiedConnection != null ? specifiedConnection : null;
1635
16360 if(connection instanceof Error) return callback(connection, null);
1637
1638 // Fetch either a reader or writer dependent on the specified read option if no connection
1639 // was passed in
16400 if(connection == null) {
16410 connection = self.serverConfig.checkoutReader(read);
1642 }
1643
16440 if(connection == null) {
16450 return callback(new Error("no open connections"));
16460 } else if(connection instanceof Error || connection['message'] != null) {
16470 return callback(connection);
1648 }
1649
1650 // Exhaust Option
16510 var exhaust = options.exhaust || false;
1652
1653 // Register the handler in the data structure
16540 self.serverConfig._registerHandler(db_command, raw, connection, exhaust, callback);
1655
1656 // Write the message out and handle any errors if there are any
16570 connection.write(db_command, function(err) {
16580 if(err != null) {
1659 // Call the handler with an error
16600 if(Array.isArray(db_command))
16610 self.serverConfig._callHandler(db_command[0].getRequestId(), null, err);
1662 else
16630 self.serverConfig._callHandler(db_command.getRequestId(), null, err);
1664 }
1665 });
16660 } else if(typeof callback === 'function' && onAll) {
16670 var connections = self.serverConfig.allRawConnections();
16680 var numberOfEntries = connections.length;
1669 // Go through all the connections
16700 for(var i = 0; i < connections.length; i++) {
1671 // Fetch a connection
16720 var connection = connections[i];
1673
1674 // Ensure we have a valid connection
16750 if(connection == null) {
16760 return callback(new Error("no open connections"));
16770 } else if(connection instanceof Error) {
16780 return callback(connection);
1679 }
1680
1681 // Register the handler in the data structure
16820 self.serverConfig._registerHandler(db_command, raw, connection, callback);
1683
1684 // Write the message out
16850 connection.write(db_command, function(err) {
1686 // Adjust the number of entries we need to process
16870 numberOfEntries = numberOfEntries - 1;
1688 // Remove listener
16890 if(err != null) {
1690 // Clean up listener and return error
16910 self.serverConfig._removeHandler(db_command.getRequestId());
1692 }
1693
1694 // No more entries to process callback with the error
16950 if(numberOfEntries <= 0) {
16960 callback(err);
1697 }
1698 });
1699
1700 // Update the db_command request id
17010 db_command.updateRequestId();
1702 }
1703 } else {
1704 // Fetch either a reader or writer dependent on the specified read option
1705 // var connection = read == null || read == 'primary' || read == false ? self.serverConfig.checkoutWriter(true) : self.serverConfig.checkoutReader(read);
17060 var connection = self.serverConfig.checkoutReader(read);
1707 // Override connection if needed
17080 connection = specifiedConnection != null ? specifiedConnection : connection;
1709 // Ensure we have a valid connection
17100 if(connection == null || connection instanceof Error || connection['message'] != null) return null;
1711 // Write the message out
17120 connection.write(db_command, function(err) {
17130 if(err != null) {
1714 // Emit the error
17150 self.emit("error", err);
1716 }
1717 });
1718 }
1719};
1720
1721/**
1722 * Execute db query command (not safe)
1723 * @ignore
1724 * @api private
1725 */
17261Db.prototype._executeQueryCommand = function(db_command, options, callback) {
17270 var self = this;
1728
1729 // Unpack the parameters
17300 if (typeof callback === 'undefined') {
17310 callback = options;
17320 options = {};
1733 }
1734
1735 // fast fail option used for HA, no retry
17360 var failFast = options['failFast'] != null
1737 ? options['failFast']
1738 : false;
1739
1740 // Check if the user force closed the command
17410 if(this._applicationClosed) {
17420 var err = new Error("db closed by application");
17430 if('function' == typeof callback) {
17440 return callback(err, null);
1745 } else {
17460 throw err;
1747 }
1748 }
1749
17500 if(this.serverConfig.isDestroyed())
17510 return callback(new Error("Connection was destroyed by application"));
1752
1753 // Specific connection
17540 var connection = options.connection;
1755 // Check if the connection is actually live
17560 if(connection
17570 && (!connection.isConnected || !connection.isConnected())) connection = null;
1758
1759 // Get the configuration
17600 var config = this.serverConfig;
17610 var read = options.read;
1762 // Allow for the usage of the readPreference model
17630 if(read == null) {
17640 read = options.readPreference;
1765 }
1766
17670 if(!connection && !config.canRead(read) && !config.canWrite() && config.isAutoReconnect()) {
17680 if(read == ReadPreference.PRIMARY
1769 || read == ReadPreference.PRIMARY_PREFERRED
1770 || (read != null && typeof read == 'object' && read.mode)
1771 || read == null) {
1772
1773 // Save the command
17740 self.serverConfig._commandsStore.read_from_writer(
1775 { type: 'query'
1776 , db_command: db_command
1777 , options: options
1778 , callback: callback
1779 , db: self
1780 , executeQueryCommand: __executeQueryCommand
1781 , executeInsertCommand: __executeInsertCommand
1782 }
1783 );
1784 } else {
17850 self.serverConfig._commandsStore.read(
1786 { type: 'query'
1787 , db_command: db_command
1788 , options: options
1789 , callback: callback
1790 , db: self
1791 , executeQueryCommand: __executeQueryCommand
1792 , executeInsertCommand: __executeInsertCommand
1793 }
1794 );
1795 }
1796
1797 // If we have blown through the number of items let's
17980 if(!self.serverConfig._commandsStore.validateBufferLimit(self.bufferMaxEntries)) {
17990 self.close();
1800 }
18010 } else if(!connection && !config.canRead(read) && !config.canWrite() && !config.isAutoReconnect()) {
18020 return callback(new Error("no open connections"), null);
1803 } else {
18040 if(typeof callback == 'function') {
18050 __executeQueryCommand(self, db_command, options, function (err, result, conn) {
18060 callback(err, result, conn);
1807 });
1808 } else {
18090 __executeQueryCommand(self, db_command, options);
1810 }
1811 }
1812};
1813
1814/**
1815 * @ignore
1816 */
18171var __executeInsertCommand = function(self, db_command, options, callback) {
1818 // Always checkout a writer for this kind of operations
18190 var connection = self.serverConfig.checkoutWriter();
1820 // Get safe mode
18210 var safe = options['safe'] != null ? options['safe'] : false;
18220 var raw = options['raw'] != null ? options['raw'] : self.raw;
18230 var specifiedConnection = options['connection'] != null ? options['connection'] : null;
1824 // Override connection if needed
18250 connection = specifiedConnection != null ? specifiedConnection : connection;
1826
1827 // Validate if we can use this server 2.6 wire protocol
18280 if(!connection.isCompatible()) {
18290 return callback(utils.toError("driver is incompatible with this server version"), null);
1830 }
1831
1832 // Ensure we have a valid connection
18330 if(typeof callback === 'function') {
1834 // Ensure we have a valid connection
18350 if(connection == null) {
18360 return callback(new Error("no open connections"));
18370 } else if(connection instanceof Error) {
18380 return callback(connection);
1839 }
1840
18410 var errorOptions = _getWriteConcern(self, options);
18420 if(errorOptions.w > 0 || errorOptions.w == 'majority' || errorOptions.j || errorOptions.journal || errorOptions.fsync) {
1843 // db command is now an array of commands (original command + lastError)
18440 db_command = [db_command, DbCommand.createGetLastErrorCommand(safe, self)];
1845 // Register the handler in the data structure
18460 self.serverConfig._registerHandler(db_command[1], raw, connection, callback);
1847 }
1848 }
1849
1850 // If we have no callback and there is no connection
18510 if(connection == null) return null;
18520 if(connection instanceof Error && typeof callback == 'function') return callback(connection, null);
18530 if(connection instanceof Error) return null;
18540 if(connection == null && typeof callback == 'function') return callback(new Error("no primary server found"), null);
1855
1856 // Write the message out
18570 connection.write(db_command, function(err) {
1858 // Return the callback if it's not a safe operation and the callback is defined
18590 if(typeof callback === 'function' && (safe == null || safe == false)) {
1860 // Perform the callback
18610 callback(err, null);
18620 } else if(typeof callback === 'function') {
1863 // Call the handler with an error
18640 self.serverConfig._callHandler(db_command[1].getRequestId(), null, err);
18650 } else if(typeof callback == 'function' && safe && safe.w == -1) {
1866 // Call the handler with no error
18670 self.serverConfig._callHandler(db_command[1].getRequestId(), null, null);
18680 } else if(!safe || safe.w == -1) {
18690 self.emit("error", err);
1870 }
1871 });
1872};
1873
1874/**
1875 * Execute an insert Command
1876 * @ignore
1877 * @api private
1878 */
18791Db.prototype._executeInsertCommand = function(db_command, options, callback) {
18800 var self = this;
1881
1882 // Unpack the parameters
18830 if(callback == null && typeof options === 'function') {
18840 callback = options;
18850 options = {};
1886 }
1887
1888 // Ensure options are not null
18890 options = options == null ? {} : options;
1890
1891 // Check if the user force closed the command
18920 if(this._applicationClosed) {
18930 if(typeof callback == 'function') {
18940 return callback(new Error("db closed by application"), null);
1895 } else {
18960 throw new Error("db closed by application");
1897 }
1898 }
1899
19000 if(this.serverConfig.isDestroyed()) return callback(new Error("Connection was destroyed by application"));
1901
1902 // Specific connection
19030 var connection = options.connection;
1904 // Check if the connection is actually live
19050 if(connection
19060 && (!connection.isConnected || !connection.isConnected())) connection = null;
1907
1908 // Get config
19090 var config = self.serverConfig;
1910 // Check if we are connected
19110 if(!connection && !config.canWrite() && config.isAutoReconnect()) {
19120 self.serverConfig._commandsStore.write(
1913 { type:'insert'
1914 , 'db_command':db_command
1915 , 'options':options
1916 , 'callback':callback
1917 , db: self
1918 , executeQueryCommand: __executeQueryCommand
1919 , executeInsertCommand: __executeInsertCommand
1920 }
1921 );
1922
1923 // If we have blown through the number of items let's
19240 if(!self.serverConfig._commandsStore.validateBufferLimit(self.bufferMaxEntries)) {
19250 self.close();
1926 }
19270 } else if(!connection && !config.canWrite() && !config.isAutoReconnect()) {
19280 return callback(new Error("no open connections"), null);
1929 } else {
19300 __executeInsertCommand(self, db_command, options, callback);
1931 }
1932};
1933
1934/**
1935 * Update command is the same
1936 * @ignore
1937 * @api private
1938 */
19391Db.prototype._executeUpdateCommand = Db.prototype._executeInsertCommand;
1940/**
1941 * Remove command is the same
1942 * @ignore
1943 * @api private
1944 */
19451Db.prototype._executeRemoveCommand = Db.prototype._executeInsertCommand;
1946
1947/**
1948 * Wrap a Mongo error document into an Error instance.
1949 * Deprecated. Use utils.toError instead.
1950 *
1951 * @ignore
1952 * @api private
1953 * @deprecated
1954 */
19551Db.prototype.wrap = utils.toError;
1956
1957/**
1958 * Default URL
1959 *
1960 * @classconstant DEFAULT_URL
1961 **/
19621Db.DEFAULT_URL = 'mongodb://localhost:27017/default';
1963
1964/**
1965 * Connect to MongoDB using a url as documented at
1966 *
1967 * docs.mongodb.org/manual/reference/connection-string/
1968 *
1969 * Options
1970 * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication
1971 * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor**
1972 * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor**
1973 * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor**
1974 * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor**
1975 *
1976 * @param {String} url connection url for MongoDB.
1977 * @param {Object} [options] optional options for insert command
1978 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the db instance or null if an error occurred.
1979 * @return {null}
1980 * @api public
1981 */
19821Db.connect = function(url, options, callback) {
1983 // Ensure correct mapping of the callback
19840 if(typeof options == 'function') {
19850 callback = options;
19860 options = {};
1987 }
1988
1989 // Ensure same behavior as previous version w:0
19900 if(url.indexOf("safe") == -1
1991 && url.indexOf("w") == -1
1992 && url.indexOf("journal") == -1 && url.indexOf("j") == -1
19930 && url.indexOf("fsync") == -1) options.w = 0;
1994
1995 // Avoid circular require problem
19960 var MongoClient = require('./mongo_client.js').MongoClient;
1997 // Attempt to connect
19980 MongoClient.connect.call(MongoClient, url, options, callback);
1999};
2000
2001/**
2002 * State of the db connection
2003 * @ignore
2004 */
20051Object.defineProperty(Db.prototype, "state", { enumerable: true
2006 , get: function () {
20070 return this.serverConfig._serverState;
2008 }
2009});
2010
2011/**
2012 * @ignore
2013 */
20141var _hasWriteConcern = function(errorOptions) {
20150 return errorOptions == true
2016 || errorOptions.w > 0
2017 || errorOptions.w == 'majority'
2018 || errorOptions.j == true
2019 || errorOptions.journal == true
2020 || errorOptions.fsync == true
2021};
2022
2023/**
2024 * @ignore
2025 */
20261var _setWriteConcernHash = function(options) {
20270 var finalOptions = {};
20280 if(options.w != null) finalOptions.w = options.w;
20290 if(options.journal == true) finalOptions.j = options.journal;
20300 if(options.j == true) finalOptions.j = options.j;
20310 if(options.fsync == true) finalOptions.fsync = options.fsync;
20320 if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout;
20330 return finalOptions;
2034};
2035
2036/**
2037 * @ignore
2038 */
20391var _getWriteConcern = function(self, options, callback) {
2040 // Final options
20410 var finalOptions = {w:1};
2042 // Local options verification
20430 if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') {
20440 finalOptions = _setWriteConcernHash(options);
20450 } else if(options.safe != null && typeof options.safe == 'object') {
20460 finalOptions = _setWriteConcernHash(options.safe);
20470 } else if(typeof options.safe == "boolean") {
20480 finalOptions = {w: (options.safe ? 1 : 0)};
20490 } else if(self.options.w != null || typeof self.options.j == 'boolean' || typeof self.options.journal == 'boolean' || typeof self.options.fsync == 'boolean') {
20500 finalOptions = _setWriteConcernHash(self.options);
20510 } else if(self.safe.w != null || typeof self.safe.j == 'boolean' || typeof self.safe.journal == 'boolean' || typeof self.safe.fsync == 'boolean') {
20520 finalOptions = _setWriteConcernHash(self.safe);
20530 } else if(typeof self.safe == "boolean") {
20540 finalOptions = {w: (self.safe ? 1 : 0)};
2055 }
2056
2057 // Ensure we don't have an invalid combination of write concerns
20580 if(finalOptions.w < 1
20590 && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowledgement using w < 1 cannot be combined with journal:true or fsync:true");
2060
2061 // Return the options
20620 return finalOptions;
2063};
2064
2065/**
2066 * Legacy support
2067 *
2068 * @ignore
2069 * @api private
2070 */
20711exports.connect = Db.connect;
20721exports.Db = Db;
2073
2074/**
2075 * Remove all listeners to the db instance.
2076 * @ignore
2077 * @api private
2078 */
20791Db.prototype.removeAllEventListeners = function() {
20800 this.removeAllListeners("close");
20810 this.removeAllListeners("error");
20820 this.removeAllListeners("timeout");
20830 this.removeAllListeners("parseError");
20840 this.removeAllListeners("poolReady");
20850 this.removeAllListeners("message");
2086};
2087

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/gridfs/chunk.js

16%
77
13
64
LineHitsSource
11var Binary = require('bson').Binary,
2 ObjectID = require('bson').ObjectID;
3
4/**
5 * Class for representing a single chunk in GridFS.
6 *
7 * @class
8 *
9 * @param file {GridStore} The {@link GridStore} object holding this chunk.
10 * @param mongoObject {object} The mongo object representation of this chunk.
11 *
12 * @throws Error when the type of data field for {@link mongoObject} is not
13 * supported. Currently supported types for data field are instances of
14 * {@link String}, {@link Array}, {@link Binary} and {@link Binary}
15 * from the bson module
16 *
17 * @see Chunk#buildMongoObject
18 */
191var Chunk = exports.Chunk = function(file, mongoObject, writeConcern) {
200 if(!(this instanceof Chunk)) return new Chunk(file, mongoObject);
21
220 this.file = file;
230 var self = this;
240 var mongoObjectFinal = mongoObject == null ? {} : mongoObject;
250 this.writeConcern = writeConcern || {w:1};
260 this.objectId = mongoObjectFinal._id == null ? new ObjectID() : mongoObjectFinal._id;
270 this.chunkNumber = mongoObjectFinal.n == null ? 0 : mongoObjectFinal.n;
280 this.data = new Binary();
29
300 if(mongoObjectFinal.data == null) {
310 } else if(typeof mongoObjectFinal.data == "string") {
320 var buffer = new Buffer(mongoObjectFinal.data.length);
330 buffer.write(mongoObjectFinal.data, 'binary', 0);
340 this.data = new Binary(buffer);
350 } else if(Array.isArray(mongoObjectFinal.data)) {
360 var buffer = new Buffer(mongoObjectFinal.data.length);
370 buffer.write(mongoObjectFinal.data.join(''), 'binary', 0);
380 this.data = new Binary(buffer);
390 } else if(mongoObjectFinal.data instanceof Binary || Object.prototype.toString.call(mongoObjectFinal.data) == "[object Binary]") {
400 this.data = mongoObjectFinal.data;
410 } else if(Buffer.isBuffer(mongoObjectFinal.data)) {
42 } else {
430 throw Error("Illegal chunk format");
44 }
45 // Update position
460 this.internalPosition = 0;
47};
48
49/**
50 * Writes a data to this object and advance the read/write head.
51 *
52 * @param data {string} the data to write
53 * @param callback {function(*, GridStore)} This will be called after executing
54 * this method. The first parameter will contain null and the second one
55 * will contain a reference to this object.
56 */
571Chunk.prototype.write = function(data, callback) {
580 this.data.write(data, this.internalPosition);
590 this.internalPosition = this.data.length();
600 if(callback != null) return callback(null, this);
610 return this;
62};
63
64/**
65 * Reads data and advances the read/write head.
66 *
67 * @param length {number} The length of data to read.
68 *
69 * @return {string} The data read if the given length will not exceed the end of
70 * the chunk. Returns an empty String otherwise.
71 */
721Chunk.prototype.read = function(length) {
73 // Default to full read if no index defined
740 length = length == null || length == 0 ? this.length() : length;
75
760 if(this.length() - this.internalPosition + 1 >= length) {
770 var data = this.data.read(this.internalPosition, length);
780 this.internalPosition = this.internalPosition + length;
790 return data;
80 } else {
810 return '';
82 }
83};
84
851Chunk.prototype.readSlice = function(length) {
860 if ((this.length() - this.internalPosition) >= length) {
870 var data = null;
880 if (this.data.buffer != null) { //Pure BSON
890 data = this.data.buffer.slice(this.internalPosition, this.internalPosition + length);
90 } else { //Native BSON
910 data = new Buffer(length);
920 length = this.data.readInto(data, this.internalPosition);
93 }
940 this.internalPosition = this.internalPosition + length;
950 return data;
96 } else {
970 return null;
98 }
99};
100
101/**
102 * Checks if the read/write head is at the end.
103 *
104 * @return {boolean} Whether the read/write head has reached the end of this
105 * chunk.
106 */
1071Chunk.prototype.eof = function() {
1080 return this.internalPosition == this.length() ? true : false;
109};
110
111/**
112 * Reads one character from the data of this chunk and advances the read/write
113 * head.
114 *
115 * @return {string} a single character data read if the the read/write head is
116 * not at the end of the chunk. Returns an empty String otherwise.
117 */
1181Chunk.prototype.getc = function() {
1190 return this.read(1);
120};
121
122/**
123 * Clears the contents of the data in this chunk and resets the read/write head
124 * to the initial position.
125 */
1261Chunk.prototype.rewind = function() {
1270 this.internalPosition = 0;
1280 this.data = new Binary();
129};
130
131/**
132 * Saves this chunk to the database. Also overwrites existing entries having the
133 * same id as this chunk.
134 *
135 * @param callback {function(*, GridStore)} This will be called after executing
136 * this method. The first parameter will contain null and the second one
137 * will contain a reference to this object.
138 */
1391Chunk.prototype.save = function(callback) {
1400 var self = this;
141
1420 self.file.chunkCollection(function(err, collection) {
1430 if(err) return callback(err);
144
1450 collection.remove({'_id':self.objectId}, self.writeConcern, function(err, result) {
1460 if(err) return callback(err);
147
1480 if(self.data.length() > 0) {
1490 self.buildMongoObject(function(mongoObject) {
1500 var options = {forceServerObjectId:true};
1510 for(var name in self.writeConcern) {
1520 options[name] = self.writeConcern[name];
153 }
154
1550 collection.insert(mongoObject, options, function(err, collection) {
1560 callback(err, self);
157 });
158 });
159 } else {
1600 callback(null, self);
161 }
162 });
163 });
164};
165
166/**
167 * Creates a mongoDB object representation of this chunk.
168 *
169 * @param callback {function(Object)} This will be called after executing this
170 * method. The object will be passed to the first parameter and will have
171 * the structure:
172 *
173 * <pre><code>
174 * {
175 * '_id' : , // {number} id for this chunk
176 * 'files_id' : , // {number} foreign key to the file collection
177 * 'n' : , // {number} chunk number
178 * 'data' : , // {bson#Binary} the chunk data itself
179 * }
180 * </code></pre>
181 *
182 * @see <a href="http://www.mongodb.org/display/DOCS/GridFS+Specification#GridFSSpecification-{{chunks}}">MongoDB GridFS Chunk Object Structure</a>
183 */
1841Chunk.prototype.buildMongoObject = function(callback) {
1850 var mongoObject = {
186 'files_id': this.file.fileId,
187 'n': this.chunkNumber,
188 'data': this.data};
189 // If we are saving using a specific ObjectId
1900 if(this.objectId != null) mongoObject._id = this.objectId;
191
1920 callback(mongoObject);
193};
194
195/**
196 * @return {number} the length of the data
197 */
1981Chunk.prototype.length = function() {
1990 return this.data.length();
200};
201
202/**
203 * The position of the read/write head
204 * @name position
205 * @lends Chunk#
206 * @field
207 */
2081Object.defineProperty(Chunk.prototype, "position", { enumerable: true
209 , get: function () {
2100 return this.internalPosition;
211 }
212 , set: function(value) {
2130 this.internalPosition = value;
214 }
215});
216
217/**
218 * The default chunk size
219 * @constant
220 */
2211Chunk.DEFAULT_CHUNK_SIZE = 1024 * 256;
222

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/gridfs/grid.js

18%
33
6
27
LineHitsSource
11var GridStore = require('./gridstore').GridStore,
2 ObjectID = require('bson').ObjectID;
3
4/**
5 * A class representation of a simple Grid interface.
6 *
7 * @class Represents the Grid.
8 * @param {Db} db A database instance to interact with.
9 * @param {String} [fsName] optional different root collection for GridFS.
10 * @return {Grid}
11 */
121function Grid(db, fsName) {
13
140 if(!(this instanceof Grid)) return new Grid(db, fsName);
15
160 this.db = db;
170 this.fsName = fsName == null ? GridStore.DEFAULT_ROOT_COLLECTION : fsName;
18}
19
20/**
21 * Puts binary data to the grid
22 *
23 * Options
24 * - **_id** {Any}, unique id for this file
25 * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
26 * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**.
27 * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**.
28 * - **metadata** {Object}, arbitrary data the user wants to store.
29 *
30 * @param {Buffer} data buffer with Binary Data.
31 * @param {Object} [options] the options for the files.
32 * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
33 * @return {null}
34 * @api public
35 */
361Grid.prototype.put = function(data, options, callback) {
370 var self = this;
380 var args = Array.prototype.slice.call(arguments, 1);
390 callback = args.pop();
400 options = args.length ? args.shift() : {};
41 // If root is not defined add our default one
420 options['root'] = options['root'] == null ? this.fsName : options['root'];
43
44 // Return if we don't have a buffer object as data
450 if(!(Buffer.isBuffer(data))) return callback(new Error("Data object must be a buffer object"), null);
46 // Get filename if we are using it
470 var filename = options['filename'] || null;
48 // Get id if we are using it
490 var id = options['_id'] || null;
50 // Create gridstore
510 var gridStore = new GridStore(this.db, id, filename, "w", options);
520 gridStore.open(function(err, gridStore) {
530 if(err) return callback(err, null);
54
550 gridStore.write(data, function(err, result) {
560 if(err) return callback(err, null);
57
580 gridStore.close(function(err, result) {
590 if(err) return callback(err, null);
600 callback(null, result);
61 })
62 })
63 })
64}
65
66/**
67 * Get binary data to the grid
68 *
69 * @param {Any} id for file.
70 * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
71 * @return {null}
72 * @api public
73 */
741Grid.prototype.get = function(id, callback) {
75 // Create gridstore
760 var gridStore = new GridStore(this.db, id, null, "r", {root:this.fsName});
770 gridStore.open(function(err, gridStore) {
780 if(err) return callback(err, null);
79
80 // Return the data
810 gridStore.read(function(err, data) {
820 return callback(err, data)
83 });
84 })
85}
86
87/**
88 * Delete file from grid
89 *
90 * @param {Any} id for file.
91 * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
92 * @return {null}
93 * @api public
94 */
951Grid.prototype.delete = function(id, callback) {
96 // Create gridstore
970 GridStore.unlink(this.db, id, {root:this.fsName}, function(err, result) {
980 if(err) return callback(err, false);
990 return callback(null, true);
100 });
101}
102
1031exports.Grid = Grid;
104

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js

9%
621
62
559
LineHitsSource
1/**
2 * @fileOverview GridFS is a tool for MongoDB to store files to the database.
3 * Because of the restrictions of the object size the database can hold, a
4 * facility to split a file into several chunks is needed. The {@link GridStore}
5 * class offers a simplified api to interact with files while managing the
6 * chunks of split files behind the scenes. More information about GridFS can be
7 * found <a href="http://www.mongodb.org/display/DOCS/GridFS">here</a>.
8 */
91var Chunk = require('./chunk').Chunk,
10 DbCommand = require('../commands/db_command').DbCommand,
11 ObjectID = require('bson').ObjectID,
12 Buffer = require('buffer').Buffer,
13 fs = require('fs'),
14 timers = require('timers'),
15 util = require('util'),
16 inherits = util.inherits,
17 ReadStream = require('./readstream').ReadStream,
18 Stream = require('stream');
19
20// Set processor, setImmediate if 0.10 otherwise nextTick
211var processor = require('../utils').processor();
22
231var REFERENCE_BY_FILENAME = 0,
24 REFERENCE_BY_ID = 1;
25
26/**
27 * A class representation of a file stored in GridFS.
28 *
29 * Modes
30 * - **"r"** - read only. This is the default mode.
31 * - **"w"** - write in truncate mode. Existing data will be overwriten.
32 * - **w+"** - write in edit mode.
33 *
34 * Options
35 * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
36 * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**.
37 * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**.
38 * - **metadata** {Object}, arbitrary data the user wants to store.
39 * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
40 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
41 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
42 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
43 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
44 *
45 * @class Represents the GridStore.
46 * @param {Db} db A database instance to interact with.
47 * @param {Any} [id] optional unique id for this file
48 * @param {String} [filename] optional filename for this file, no unique constrain on the field
49 * @param {String} mode set the mode for this file.
50 * @param {Object} options optional properties to specify.
51 * @return {GridStore}
52 */
531var GridStore = function GridStore(db, id, filename, mode, options) {
540 if(!(this instanceof GridStore)) return new GridStore(db, id, filename, mode, options);
55
560 var self = this;
570 this.db = db;
58
59 // Call stream constructor
600 if(typeof Stream == 'function') {
610 Stream.call(this);
62 } else {
63 // 0.4.X backward compatibility fix
640 Stream.Stream.call(this);
65 }
66
67 // Handle options
680 if(typeof options === 'undefined') options = {};
69 // Handle mode
700 if(typeof mode === 'undefined') {
710 mode = filename;
720 filename = undefined;
730 } else if(typeof mode == 'object') {
740 options = mode;
750 mode = filename;
760 filename = undefined;
77 }
78
790 if(id instanceof ObjectID) {
800 this.referenceBy = REFERENCE_BY_ID;
810 this.fileId = id;
820 this.filename = filename;
830 } else if(typeof filename == 'undefined') {
840 this.referenceBy = REFERENCE_BY_FILENAME;
850 this.filename = id;
860 if (mode.indexOf('w') != null) {
870 this.fileId = new ObjectID();
88 }
89 } else {
900 this.referenceBy = REFERENCE_BY_ID;
910 this.fileId = id;
920 this.filename = filename;
93 }
94
95 // Set up the rest
960 this.mode = mode == null ? "r" : mode;
970 this.options = options == null ? {w:1} : options;
98
99 // If we have no write concerns set w:1 as default
1000 if(this.options.w == null
101 && this.options.j == null
1020 && this.options.fsync == null) this.options.w = 1;
103
104 // Set the root if overridden
1050 this.root = this.options['root'] == null ? exports.GridStore.DEFAULT_ROOT_COLLECTION : this.options['root'];
1060 this.position = 0;
1070 this.readPreference = this.options.readPreference || 'primary';
1080 this.writeConcern = _getWriteConcern(this, this.options);
109 // Set default chunk size
1100 this.internalChunkSize = this.options['chunkSize'] == null ? Chunk.DEFAULT_CHUNK_SIZE : this.options['chunkSize'];
111}
112
113/**
114 * Code for the streaming capabilities of the gridstore object
115 * Most code from Aaron heckmanns project https://github.com/aheckmann/gridfs-stream
116 * Modified to work on the gridstore object itself
117 * @ignore
118 */
1191if(typeof Stream == 'function') {
1201 GridStore.prototype = { __proto__: Stream.prototype }
121} else {
122 // Node 0.4.X compatibility code
1230 GridStore.prototype = { __proto__: Stream.Stream.prototype }
124}
125
126// Move pipe to _pipe
1271GridStore.prototype._pipe = GridStore.prototype.pipe;
128
129/**
130 * Opens the file from the database and initialize this object. Also creates a
131 * new one if file does not exist.
132 *
133 * @param {Function} callback this will be called after executing this method. The first parameter will contain an **{Error}** object and the second parameter will be null if an error occured. Otherwise, the first parameter will be null and the second will contain the reference to this object.
134 * @return {null}
135 * @api public
136 */
1371GridStore.prototype.open = function(callback) {
1380 if( this.mode != "w" && this.mode != "w+" && this.mode != "r"){
1390 callback(new Error("Illegal mode " + this.mode), null);
1400 return;
141 }
142
1430 var self = this;
144 // If we are writing we need to ensure we have the right indexes for md5's
1450 if((self.mode == "w" || self.mode == "w+")) {
146 // Get files collection
1470 self.collection(function(err, collection) {
1480 if(err) return callback(err);
149
150 // Put index on filename
1510 collection.ensureIndex([['filename', 1]], function(err, index) {
1520 if(err) return callback(err);
153
154 // Get chunk collection
1550 self.chunkCollection(function(err, chunkCollection) {
1560 if(err) return callback(err);
157
158 // Ensure index on chunk collection
1590 chunkCollection.ensureIndex([['files_id', 1], ['n', 1]], function(err, index) {
1600 if(err) return callback(err);
1610 _open(self, callback);
162 });
163 });
164 });
165 });
166 } else {
167 // Open the gridstore
1680 _open(self, callback);
169 }
170};
171
172/**
173 * Hidding the _open function
174 * @ignore
175 * @api private
176 */
1771var _open = function(self, callback) {
1780 self.collection(function(err, collection) {
1790 if(err!==null) {
1800 callback(new Error("at collection: "+err), null);
1810 return;
182 }
183
184 // Create the query
1850 var query = self.referenceBy == REFERENCE_BY_ID ? {_id:self.fileId} : {filename:self.filename};
1860 query = null == self.fileId && this.filename == null ? null : query;
187
188 // Fetch the chunks
1890 if(query != null) {
1900 collection.find(query, {readPreference:self.readPreference}, function(err, cursor) {
1910 if(err) return error(err);
192
193 // Fetch the file
1940 cursor.nextObject(function(err, doc) {
1950 if(err) return error(err);
196
197 // Check if the collection for the files exists otherwise prepare the new one
1980 if(doc != null) {
1990 self.fileId = doc._id;
2000 self.filename = doc.filename;
2010 self.contentType = doc.contentType;
2020 self.internalChunkSize = doc.chunkSize;
2030 self.uploadDate = doc.uploadDate;
2040 self.aliases = doc.aliases;
2050 self.length = doc.length;
2060 self.metadata = doc.metadata;
2070 self.internalMd5 = doc.md5;
2080 } else if (self.mode != 'r') {
2090 self.fileId = self.fileId == null ? new ObjectID() : self.fileId;
2100 self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE;
2110 self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize;
2120 self.length = 0;
213 } else {
2140 self.length = 0;
2150 var txtId = self.fileId instanceof ObjectID ? self.fileId.toHexString() : self.fileId;
2160 return error(new Error((self.referenceBy == REFERENCE_BY_ID ? txtId : self.filename) + " does not exist", self));
217 }
218
219 // Process the mode of the object
2200 if(self.mode == "r") {
2210 nthChunk(self, 0, function(err, chunk) {
2220 if(err) return error(err);
2230 self.currentChunk = chunk;
2240 self.position = 0;
2250 callback(null, self);
226 });
2270 } else if(self.mode == "w") {
228 // Delete any existing chunks
2290 deleteChunks(self, function(err, result) {
2300 if(err) return error(err);
2310 self.currentChunk = new Chunk(self, {'n':0}, self.writeConcern);
2320 self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type'];
2330 self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size'];
2340 self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
2350 self.position = 0;
2360 callback(null, self);
237 });
2380 } else if(self.mode == "w+") {
2390 nthChunk(self, lastChunkNumber(self), function(err, chunk) {
2400 if(err) return error(err);
241 // Set the current chunk
2420 self.currentChunk = chunk == null ? new Chunk(self, {'n':0}, self.writeConcern) : chunk;
2430 self.currentChunk.position = self.currentChunk.data.length();
2440 self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
2450 self.position = self.length;
2460 callback(null, self);
247 });
248 }
249 });
250 });
251 } else {
252 // Write only mode
2530 self.fileId = null == self.fileId ? new ObjectID() : self.fileId;
2540 self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE;
2550 self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize;
2560 self.length = 0;
257
2580 self.chunkCollection(function(err, collection2) {
2590 if(err) return error(err);
260
261 // No file exists set up write mode
2620 if(self.mode == "w") {
263 // Delete any existing chunks
2640 deleteChunks(self, function(err, result) {
2650 if(err) return error(err);
2660 self.currentChunk = new Chunk(self, {'n':0}, self.writeConcern);
2670 self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type'];
2680 self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size'];
2690 self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
2700 self.position = 0;
2710 callback(null, self);
272 });
2730 } else if(self.mode == "w+") {
2740 nthChunk(self, lastChunkNumber(self), function(err, chunk) {
2750 if(err) return error(err);
276 // Set the current chunk
2770 self.currentChunk = chunk == null ? new Chunk(self, {'n':0}, self.writeConcern) : chunk;
2780 self.currentChunk.position = self.currentChunk.data.length();
2790 self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
2800 self.position = self.length;
2810 callback(null, self);
282 });
283 }
284 });
285 }
286 });
287
288 // only pass error to callback once
2890 function error (err) {
2900 if(error.err) return;
2910 callback(error.err = err);
292 }
293};
294
295/**
296 * Stores a file from the file system to the GridFS database.
297 *
298 * @param {String|Buffer|FileHandle} file the file to store.
299 * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the the second will contain the reference to this object.
300 * @return {null}
301 * @api public
302 */
3031GridStore.prototype.writeFile = function (file, callback) {
3040 var self = this;
3050 if (typeof file === 'string') {
3060 fs.open(file, 'r', function (err, fd) {
3070 if(err) return callback(err);
3080 self.writeFile(fd, callback);
309 });
3100 return;
311 }
312
3130 self.open(function (err, self) {
3140 if(err) return callback(err, self);
315
3160 fs.fstat(file, function (err, stats) {
3170 if(err) return callback(err, self);
318
3190 var offset = 0;
3200 var index = 0;
3210 var numberOfChunksLeft = Math.min(stats.size / self.chunkSize);
322
323 // Write a chunk
3240 var writeChunk = function() {
3250 fs.read(file, self.chunkSize, offset, 'binary', function(err, data, bytesRead) {
3260 if(err) return callback(err, self);
327
3280 offset = offset + bytesRead;
329
330 // Create a new chunk for the data
3310 var chunk = new Chunk(self, {n:index++}, self.writeConcern);
3320 chunk.write(data, function(err, chunk) {
3330 if(err) return callback(err, self);
334
3350 chunk.save(function(err, result) {
3360 if(err) return callback(err, self);
337
3380 self.position = self.position + data.length;
339
340 // Point to current chunk
3410 self.currentChunk = chunk;
342
3430 if(offset >= stats.size) {
3440 fs.close(file);
3450 self.close(function(err, result) {
3460 if(err) return callback(err, self);
3470 return callback(null, self);
348 });
349 } else {
3500 return processor(writeChunk);
351 }
352 });
353 });
354 });
355 }
356
357 // Process the first write
3580 processor(writeChunk);
359 });
360 });
361};
362
363/**
364 * Writes some data. This method will work properly only if initialized with mode
365 * "w" or "w+".
366 *
367 * @param string {string} The data to write.
368 * @param close {boolean=false} opt_argument Closes this file after writing if
369 * true.
370 * @param callback {function(*, GridStore)} This will be called after executing
371 * this method. The first parameter will contain null and the second one
372 * will contain a reference to this object.
373 *
374 * @ignore
375 * @api private
376 */
3771var writeBuffer = function(self, buffer, close, callback) {
3780 if(typeof close === "function") { callback = close; close = null; }
3790 var finalClose = (close == null) ? false : close;
380
3810 if(self.mode[0] != "w") {
3820 callback(new Error((self.referenceBy == REFERENCE_BY_ID ? self.toHexString() : self.filename) + " not opened for writing"), null);
383 } else {
3840 if(self.currentChunk.position + buffer.length >= self.chunkSize) {
385 // Write out the current Chunk and then keep writing until we have less data left than a chunkSize left
386 // to a new chunk (recursively)
3870 var previousChunkNumber = self.currentChunk.chunkNumber;
3880 var leftOverDataSize = self.chunkSize - self.currentChunk.position;
3890 var firstChunkData = buffer.slice(0, leftOverDataSize);
3900 var leftOverData = buffer.slice(leftOverDataSize);
391 // A list of chunks to write out
3920 var chunksToWrite = [self.currentChunk.write(firstChunkData)];
393 // If we have more data left than the chunk size let's keep writing new chunks
3940 while(leftOverData.length >= self.chunkSize) {
395 // Create a new chunk and write to it
3960 var newChunk = new Chunk(self, {'n': (previousChunkNumber + 1)}, self.writeConcern);
3970 var firstChunkData = leftOverData.slice(0, self.chunkSize);
3980 leftOverData = leftOverData.slice(self.chunkSize);
399 // Update chunk number
4000 previousChunkNumber = previousChunkNumber + 1;
401 // Write data
4020 newChunk.write(firstChunkData);
403 // Push chunk to save list
4040 chunksToWrite.push(newChunk);
405 }
406
407 // Set current chunk with remaining data
4080 self.currentChunk = new Chunk(self, {'n': (previousChunkNumber + 1)}, self.writeConcern);
409 // If we have left over data write it
4100 if(leftOverData.length > 0) self.currentChunk.write(leftOverData);
411
412 // Update the position for the gridstore
4130 self.position = self.position + buffer.length;
414 // Total number of chunks to write
4150 var numberOfChunksToWrite = chunksToWrite.length;
416 // Write out all the chunks and then return
4170 for(var i = 0; i < chunksToWrite.length; i++) {
4180 var chunk = chunksToWrite[i];
4190 chunk.save(function(err, result) {
4200 if(err) return callback(err);
421
4220 numberOfChunksToWrite = numberOfChunksToWrite - 1;
423
4240 if(numberOfChunksToWrite <= 0) {
4250 return callback(null, self);
426 }
427 })
428 }
429 } else {
430 // Update the position for the gridstore
4310 self.position = self.position + buffer.length;
432 // We have less data than the chunk size just write it and callback
4330 self.currentChunk.write(buffer);
4340 callback(null, self);
435 }
436 }
437};
438
439/**
440 * Creates a mongoDB object representation of this object.
441 *
442 * @param callback {function(object)} This will be called after executing this
443 * method. The object will be passed to the first parameter and will have
444 * the structure:
445 *
446 * <pre><code>
447 * {
448 * '_id' : , // {number} id for this file
449 * 'filename' : , // {string} name for this file
450 * 'contentType' : , // {string} mime type for this file
451 * 'length' : , // {number} size of this file?
452 * 'chunksize' : , // {number} chunk size used by this file
453 * 'uploadDate' : , // {Date}
454 * 'aliases' : , // {array of string}
455 * 'metadata' : , // {string}
456 * }
457 * </code></pre>
458 *
459 * @ignore
460 * @api private
461 */
4621var buildMongoObject = function(self, callback) {
463 // Calcuate the length
4640 var mongoObject = {
465 '_id': self.fileId,
466 'filename': self.filename,
467 'contentType': self.contentType,
468 'length': self.position ? self.position : 0,
469 'chunkSize': self.chunkSize,
470 'uploadDate': self.uploadDate,
471 'aliases': self.aliases,
472 'metadata': self.metadata
473 };
474
4750 var md5Command = {filemd5:self.fileId, root:self.root};
4760 self.db.command(md5Command, function(err, results) {
4770 mongoObject.md5 = results.md5;
4780 callback(mongoObject);
479 });
480};
481
482/**
483 * Saves this file to the database. This will overwrite the old entry if it
484 * already exists. This will work properly only if mode was initialized to
485 * "w" or "w+".
486 *
487 * @param {Function} callback this will be called after executing this method. Passes an **{Error}** object to the first parameter and null to the second if an error occured. Otherwise, passes null to the first and a reference to this object to the second.
488 * @return {null}
489 * @api public
490 */
4911GridStore.prototype.close = function(callback) {
4920 var self = this;
493
4940 if(self.mode[0] == "w") {
4950 if(self.currentChunk != null && self.currentChunk.position > 0) {
4960 self.currentChunk.save(function(err, chunk) {
4970 if(err && typeof callback == 'function') return callback(err);
498
4990 self.collection(function(err, files) {
5000 if(err && typeof callback == 'function') return callback(err);
501
502 // Build the mongo object
5030 if(self.uploadDate != null) {
5040 files.remove({'_id':self.fileId}, {safe:true}, function(err, collection) {
5050 if(err && typeof callback == 'function') return callback(err);
506
5070 buildMongoObject(self, function(mongoObject) {
5080 files.save(mongoObject, self.writeConcern, function(err) {
5090 if(typeof callback == 'function')
5100 callback(err, mongoObject);
511 });
512 });
513 });
514 } else {
5150 self.uploadDate = new Date();
5160 buildMongoObject(self, function(mongoObject) {
5170 files.save(mongoObject, self.writeConcern, function(err) {
5180 if(typeof callback == 'function')
5190 callback(err, mongoObject);
520 });
521 });
522 }
523 });
524 });
525 } else {
5260 self.collection(function(err, files) {
5270 if(err && typeof callback == 'function') return callback(err);
528
5290 self.uploadDate = new Date();
5300 buildMongoObject(self, function(mongoObject) {
5310 files.save(mongoObject, self.writeConcern, function(err) {
5320 if(typeof callback == 'function')
5330 callback(err, mongoObject);
534 });
535 });
536 });
537 }
5380 } else if(self.mode[0] == "r") {
5390 if(typeof callback == 'function')
5400 callback(null, null);
541 } else {
5420 if(typeof callback == 'function')
5430 callback(new Error("Illegal mode " + self.mode), null);
544 }
545};
546
547/**
548 * Gets the nth chunk of this file.
549 *
550 * @param chunkNumber {number} The nth chunk to retrieve.
551 * @param callback {function(*, Chunk|object)} This will be called after
552 * executing this method. null will be passed to the first parameter while
553 * a new {@link Chunk} instance will be passed to the second parameter if
554 * the chunk was found or an empty object {} if not.
555 *
556 * @ignore
557 * @api private
558 */
5591var nthChunk = function(self, chunkNumber, callback) {
5600 self.chunkCollection(function(err, collection) {
5610 if(err) return callback(err);
562
5630 collection.find({'files_id':self.fileId, 'n':chunkNumber}, {readPreference: self.readPreference}, function(err, cursor) {
5640 if(err) return callback(err);
565
5660 cursor.nextObject(function(err, chunk) {
5670 if(err) return callback(err);
568
5690 var finalChunk = chunk == null ? {} : chunk;
5700 callback(null, new Chunk(self, finalChunk, self.writeConcern));
571 });
572 });
573 });
574};
575
576/**
577 *
578 * @ignore
579 * @api private
580 */
5811GridStore.prototype._nthChunk = function(chunkNumber, callback) {
5820 nthChunk(this, chunkNumber, callback);
583}
584
585/**
586 * @return {Number} The last chunk number of this file.
587 *
588 * @ignore
589 * @api private
590 */
5911var lastChunkNumber = function(self) {
5920 return Math.floor(self.length/self.chunkSize);
593};
594
595/**
596 * Retrieve this file's chunks collection.
597 *
598 * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured.
599 * @return {null}
600 * @api public
601 */
6021GridStore.prototype.chunkCollection = function(callback) {
6030 this.db.collection((this.root + ".chunks"), callback);
604};
605
606/**
607 * Deletes all the chunks of this file in the database.
608 *
609 * @param callback {function(*, boolean)} This will be called after this method
610 * executes. Passes null to the first and true to the second argument.
611 *
612 * @ignore
613 * @api private
614 */
6151var deleteChunks = function(self, callback) {
6160 if(self.fileId != null) {
6170 self.chunkCollection(function(err, collection) {
6180 if(err) return callback(err, false);
6190 collection.remove({'files_id':self.fileId}, {safe:true}, function(err, result) {
6200 if(err) return callback(err, false);
6210 callback(null, true);
622 });
623 });
624 } else {
6250 callback(null, true);
626 }
627};
628
629/**
630 * Deletes all the chunks of this file in the database.
631 *
632 * @param {Function} callback this will be called after this method executes. Passes null to the first and true to the second argument.
633 * @return {null}
634 * @api public
635 */
6361GridStore.prototype.unlink = function(callback) {
6370 var self = this;
6380 deleteChunks(this, function(err) {
6390 if(err!==null) {
6400 err.message = "at deleteChunks: " + err.message;
6410 return callback(err);
642 }
643
6440 self.collection(function(err, collection) {
6450 if(err!==null) {
6460 err.message = "at collection: " + err.message;
6470 return callback(err);
648 }
649
6500 collection.remove({'_id':self.fileId}, {safe:true}, function(err) {
6510 callback(err, self);
652 });
653 });
654 });
655};
656
657/**
658 * Retrieves the file collection associated with this object.
659 *
660 * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured.
661 * @return {null}
662 * @api public
663 */
6641GridStore.prototype.collection = function(callback) {
6650 this.db.collection(this.root + ".files", callback);
666};
667
668/**
669 * Reads the data of this file.
670 *
671 * @param {String} [separator] the character to be recognized as the newline separator.
672 * @param {Function} callback This will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character.
673 * @return {null}
674 * @api public
675 */
6761GridStore.prototype.readlines = function(separator, callback) {
6770 var args = Array.prototype.slice.call(arguments, 0);
6780 callback = args.pop();
6790 separator = args.length ? args.shift() : "\n";
680
6810 this.read(function(err, data) {
6820 if(err) return callback(err);
683
6840 var items = data.toString().split(separator);
6850 items = items.length > 0 ? items.splice(0, items.length - 1) : [];
6860 for(var i = 0; i < items.length; i++) {
6870 items[i] = items[i] + separator;
688 }
689
6900 callback(null, items);
691 });
692};
693
694/**
695 * Deletes all the chunks of this file in the database if mode was set to "w" or
696 * "w+" and resets the read/write head to the initial position.
697 *
698 * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
699 * @return {null}
700 * @api public
701 */
7021GridStore.prototype.rewind = function(callback) {
7030 var self = this;
704
7050 if(this.currentChunk.chunkNumber != 0) {
7060 if(this.mode[0] == "w") {
7070 deleteChunks(self, function(err, gridStore) {
7080 if(err) return callback(err);
7090 self.currentChunk = new Chunk(self, {'n': 0}, self.writeConcern);
7100 self.position = 0;
7110 callback(null, self);
712 });
713 } else {
7140 self.currentChunk(0, function(err, chunk) {
7150 if(err) return callback(err);
7160 self.currentChunk = chunk;
7170 self.currentChunk.rewind();
7180 self.position = 0;
7190 callback(null, self);
720 });
721 }
722 } else {
7230 self.currentChunk.rewind();
7240 self.position = 0;
7250 callback(null, self);
726 }
727};
728
729/**
730 * Retrieves the contents of this file and advances the read/write head. Works with Buffers only.
731 *
732 * There are 3 signatures for this method:
733 *
734 * (callback)
735 * (length, callback)
736 * (length, buffer, callback)
737 *
738 * @param {Number} [length] the number of characters to read. Reads all the characters from the read/write head to the EOF if not specified.
739 * @param {String|Buffer} [buffer] a string to hold temporary data. This is used for storing the string data read so far when recursively calling this method.
740 * @param {Function} callback this will be called after this method is executed. null will be passed to the first parameter and a string containing the contents of the buffer concatenated with the contents read from this file will be passed to the second.
741 * @return {null}
742 * @api public
743 */
7441GridStore.prototype.read = function(length, buffer, callback) {
7450 var self = this;
746
7470 var args = Array.prototype.slice.call(arguments, 0);
7480 callback = args.pop();
7490 length = args.length ? args.shift() : null;
7500 buffer = args.length ? args.shift() : null;
751
752 // The data is a c-terminated string and thus the length - 1
7530 var finalLength = length == null ? self.length - self.position : length;
7540 var finalBuffer = buffer == null ? new Buffer(finalLength) : buffer;
755 // Add a index to buffer to keep track of writing position or apply current index
7560 finalBuffer._index = buffer != null && buffer._index != null ? buffer._index : 0;
757
7580 if((self.currentChunk.length() - self.currentChunk.position + finalBuffer._index) >= finalLength) {
7590 var slice = self.currentChunk.readSlice(finalLength - finalBuffer._index);
760 // Copy content to final buffer
7610 slice.copy(finalBuffer, finalBuffer._index);
762 // Update internal position
7630 self.position = self.position + finalBuffer.length;
764 // Check if we don't have a file at all
7650 if(finalLength == 0 && finalBuffer.length == 0) return callback(new Error("File does not exist"), null);
766 // Else return data
7670 callback(null, finalBuffer);
768 } else {
7690 var slice = self.currentChunk.readSlice(self.currentChunk.length() - self.currentChunk.position);
770 // Copy content to final buffer
7710 slice.copy(finalBuffer, finalBuffer._index);
772 // Update index position
7730 finalBuffer._index += slice.length;
774
775 // Load next chunk and read more
7760 nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) {
7770 if(err) return callback(err);
778
7790 if(chunk.length() > 0) {
7800 self.currentChunk = chunk;
7810 self.read(length, finalBuffer, callback);
782 } else {
7830 if (finalBuffer._index > 0) {
7840 callback(null, finalBuffer)
785 } else {
7860 callback(new Error("no chunks found for file, possibly corrupt"), null);
787 }
788 }
789 });
790 }
791}
792
793/**
794 * Retrieves the position of the read/write head of this file.
795 *
796 * @param {Function} callback This gets called after this method terminates. null is passed to the first parameter and the position is passed to the second.
797 * @return {null}
798 * @api public
799 */
8001GridStore.prototype.tell = function(callback) {
8010 callback(null, this.position);
802};
803
804/**
805 * Moves the read/write head to a new location.
806 *
807 * There are 3 signatures for this method
808 *
809 * Seek Location Modes
810 * - **GridStore.IO_SEEK_SET**, **(default)** set the position from the start of the file.
811 * - **GridStore.IO_SEEK_CUR**, set the position from the current position in the file.
812 * - **GridStore.IO_SEEK_END**, set the position from the end of the file.
813 *
814 * @param {Number} [position] the position to seek to
815 * @param {Number} [seekLocation] seek mode. Use one of the Seek Location modes.
816 * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
817 * @return {null}
818 * @api public
819 */
8201GridStore.prototype.seek = function(position, seekLocation, callback) {
8210 var self = this;
822
8230 var args = Array.prototype.slice.call(arguments, 1);
8240 callback = args.pop();
8250 seekLocation = args.length ? args.shift() : null;
826
8270 var seekLocationFinal = seekLocation == null ? exports.GridStore.IO_SEEK_SET : seekLocation;
8280 var finalPosition = position;
8290 var targetPosition = 0;
830
831 // Calculate the position
8320 if(seekLocationFinal == exports.GridStore.IO_SEEK_CUR) {
8330 targetPosition = self.position + finalPosition;
8340 } else if(seekLocationFinal == exports.GridStore.IO_SEEK_END) {
8350 targetPosition = self.length + finalPosition;
836 } else {
8370 targetPosition = finalPosition;
838 }
839
840 // Get the chunk
8410 var newChunkNumber = Math.floor(targetPosition/self.chunkSize);
8420 if(newChunkNumber != self.currentChunk.chunkNumber) {
8430 var seekChunk = function() {
8440 nthChunk(self, newChunkNumber, function(err, chunk) {
8450 self.currentChunk = chunk;
8460 self.position = targetPosition;
8470 self.currentChunk.position = (self.position % self.chunkSize);
8480 callback(err, self);
849 });
850 };
851
8520 if(self.mode[0] == 'w') {
8530 self.currentChunk.save(function(err) {
8540 if(err) return callback(err);
8550 seekChunk();
856 });
857 } else {
8580 seekChunk();
859 }
860 } else {
8610 self.position = targetPosition;
8620 self.currentChunk.position = (self.position % self.chunkSize);
8630 callback(null, self);
864 }
865};
866
867/**
868 * Verify if the file is at EOF.
869 *
870 * @return {Boolean} true if the read/write head is at the end of this file.
871 * @api public
872 */
8731GridStore.prototype.eof = function() {
8740 return this.position == this.length ? true : false;
875};
876
877/**
878 * Retrieves a single character from this file.
879 *
880 * @param {Function} callback this gets called after this method is executed. Passes null to the first parameter and the character read to the second or null to the second if the read/write head is at the end of the file.
881 * @return {null}
882 * @api public
883 */
8841GridStore.prototype.getc = function(callback) {
8850 var self = this;
886
8870 if(self.eof()) {
8880 callback(null, null);
8890 } else if(self.currentChunk.eof()) {
8900 nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) {
8910 self.currentChunk = chunk;
8920 self.position = self.position + 1;
8930 callback(err, self.currentChunk.getc());
894 });
895 } else {
8960 self.position = self.position + 1;
8970 callback(null, self.currentChunk.getc());
898 }
899};
900
901/**
902 * Writes a string to the file with a newline character appended at the end if
903 * the given string does not have one.
904 *
905 * @param {String} string the string to write.
906 * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
907 * @return {null}
908 * @api public
909 */
9101GridStore.prototype.puts = function(string, callback) {
9110 var finalString = string.match(/\n$/) == null ? string + "\n" : string;
9120 this.write(finalString, callback);
913};
914
915/**
916 * Returns read stream based on this GridStore file
917 *
918 * Events
919 * - **data** {function(item) {}} the data event triggers when a document is ready.
920 * - **end** {function() {}} the end event triggers when there is no more documents available.
921 * - **close** {function() {}} the close event triggers when the stream is closed.
922 * - **error** {function(err) {}} the error event triggers if an error happens.
923 *
924 * @param {Boolean} autoclose if true current GridStore will be closed when EOF and 'close' event will be fired
925 * @return {null}
926 * @api public
927 */
9281GridStore.prototype.stream = function(autoclose) {
9290 return new ReadStream(autoclose, this);
930};
931
932/**
933* The collection to be used for holding the files and chunks collection.
934*
935* @classconstant DEFAULT_ROOT_COLLECTION
936**/
9371GridStore.DEFAULT_ROOT_COLLECTION = 'fs';
938
939/**
940* Default file mime type
941*
942* @classconstant DEFAULT_CONTENT_TYPE
943**/
9441GridStore.DEFAULT_CONTENT_TYPE = 'binary/octet-stream';
945
946/**
947* Seek mode where the given length is absolute.
948*
949* @classconstant IO_SEEK_SET
950**/
9511GridStore.IO_SEEK_SET = 0;
952
953/**
954* Seek mode where the given length is an offset to the current read/write head.
955*
956* @classconstant IO_SEEK_CUR
957**/
9581GridStore.IO_SEEK_CUR = 1;
959
960/**
961* Seek mode where the given length is an offset to the end of the file.
962*
963* @classconstant IO_SEEK_END
964**/
9651GridStore.IO_SEEK_END = 2;
966
967/**
968 * Checks if a file exists in the database.
969 *
970 * Options
971 * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
972 *
973 * @param {Db} db the database to query.
974 * @param {String} name the name of the file to look for.
975 * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
976 * @param {Function} callback this will be called after this method executes. Passes null to the first and passes true to the second if the file exists and false otherwise.
977 * @return {null}
978 * @api public
979 */
9801GridStore.exist = function(db, fileIdObject, rootCollection, options, callback) {
9810 var args = Array.prototype.slice.call(arguments, 2);
9820 callback = args.pop();
9830 rootCollection = args.length ? args.shift() : null;
9840 options = args.length ? args.shift() : {};
985
986 // Establish read preference
9870 var readPreference = options.readPreference || 'primary';
988 // Fetch collection
9890 var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION;
9900 db.collection(rootCollectionFinal + ".files", function(err, collection) {
9910 if(err) return callback(err);
992
993 // Build query
9940 var query = (typeof fileIdObject == 'string' || Object.prototype.toString.call(fileIdObject) == '[object RegExp]' )
995 ? {'filename':fileIdObject}
996 : {'_id':fileIdObject}; // Attempt to locate file
997
9980 collection.find(query, {readPreference:readPreference}, function(err, cursor) {
9990 if(err) return callback(err);
1000
10010 cursor.nextObject(function(err, item) {
10020 if(err) return callback(err);
10030 callback(null, item == null ? false : true);
1004 });
1005 });
1006 });
1007};
1008
1009/**
1010 * Gets the list of files stored in the GridFS.
1011 *
1012 * @param {Db} db the database to query.
1013 * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
1014 * @param {Function} callback this will be called after this method executes. Passes null to the first and passes an array of strings containing the names of the files.
1015 * @return {null}
1016 * @api public
1017 */
10181GridStore.list = function(db, rootCollection, options, callback) {
10190 var args = Array.prototype.slice.call(arguments, 1);
10200 callback = args.pop();
10210 rootCollection = args.length ? args.shift() : null;
10220 options = args.length ? args.shift() : {};
1023
1024 // Ensure we have correct values
10250 if(rootCollection != null && typeof rootCollection == 'object') {
10260 options = rootCollection;
10270 rootCollection = null;
1028 }
1029
1030 // Establish read preference
10310 var readPreference = options.readPreference || 'primary';
1032 // Check if we are returning by id not filename
10330 var byId = options['id'] != null ? options['id'] : false;
1034 // Fetch item
10350 var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION;
10360 var items = [];
10370 db.collection((rootCollectionFinal + ".files"), function(err, collection) {
10380 if(err) return callback(err);
1039
10400 collection.find({}, {readPreference:readPreference}, function(err, cursor) {
10410 if(err) return callback(err);
1042
10430 cursor.each(function(err, item) {
10440 if(item != null) {
10450 items.push(byId ? item._id : item.filename);
1046 } else {
10470 callback(err, items);
1048 }
1049 });
1050 });
1051 });
1052};
1053
1054/**
1055 * Reads the contents of a file.
1056 *
1057 * This method has the following signatures
1058 *
1059 * (db, name, callback)
1060 * (db, name, length, callback)
1061 * (db, name, length, offset, callback)
1062 * (db, name, length, offset, options, callback)
1063 *
1064 * @param {Db} db the database to query.
1065 * @param {String} name the name of the file.
1066 * @param {Number} [length] the size of data to read.
1067 * @param {Number} [offset] the offset from the head of the file of which to start reading from.
1068 * @param {Object} [options] the options for the file.
1069 * @param {Function} callback this will be called after this method executes. A string with an error message will be passed to the first parameter when the length and offset combination exceeds the length of the file while an Error object will be passed if other forms of error occured, otherwise, a string is passed. The second parameter will contain the data read if successful or null if an error occured.
1070 * @return {null}
1071 * @api public
1072 */
10731GridStore.read = function(db, name, length, offset, options, callback) {
10740 var args = Array.prototype.slice.call(arguments, 2);
10750 callback = args.pop();
10760 length = args.length ? args.shift() : null;
10770 offset = args.length ? args.shift() : null;
10780 options = args.length ? args.shift() : null;
1079
10800 new GridStore(db, name, "r", options).open(function(err, gridStore) {
10810 if(err) return callback(err);
1082 // Make sure we are not reading out of bounds
10830 if(offset && offset >= gridStore.length) return callback("offset larger than size of file", null);
10840 if(length && length > gridStore.length) return callback("length is larger than the size of the file", null);
10850 if(offset && length && (offset + length) > gridStore.length) return callback("offset and length is larger than the size of the file", null);
1086
10870 if(offset != null) {
10880 gridStore.seek(offset, function(err, gridStore) {
10890 if(err) return callback(err);
10900 gridStore.read(length, callback);
1091 });
1092 } else {
10930 gridStore.read(length, callback);
1094 }
1095 });
1096};
1097
1098/**
1099 * Reads the data of this file.
1100 *
1101 * @param {Db} db the database to query.
1102 * @param {String} name the name of the file.
1103 * @param {String} [separator] the character to be recognized as the newline separator.
1104 * @param {Object} [options] file options.
1105 * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character.
1106 * @return {null}
1107 * @api public
1108 */
11091GridStore.readlines = function(db, name, separator, options, callback) {
11100 var args = Array.prototype.slice.call(arguments, 2);
11110 callback = args.pop();
11120 separator = args.length ? args.shift() : null;
11130 options = args.length ? args.shift() : null;
1114
11150 var finalSeperator = separator == null ? "\n" : separator;
11160 new GridStore(db, name, "r", options).open(function(err, gridStore) {
11170 if(err) return callback(err);
11180 gridStore.readlines(finalSeperator, callback);
1119 });
1120};
1121
1122/**
1123 * Deletes the chunks and metadata information of a file from GridFS.
1124 *
1125 * @param {Db} db the database to interact with.
1126 * @param {String|Array} names the name/names of the files to delete.
1127 * @param {Object} [options] the options for the files.
1128 * @callback {Function} this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
1129 * @return {null}
1130 * @api public
1131 */
11321GridStore.unlink = function(db, names, options, callback) {
11330 var self = this;
11340 var args = Array.prototype.slice.call(arguments, 2);
11350 callback = args.pop();
11360 options = args.length ? args.shift() : null;
1137
11380 if(names.constructor == Array) {
11390 var tc = 0;
11400 for(var i = 0; i < names.length; i++) {
11410 ++tc;
11420 self.unlink(db, names[i], options, function(result) {
11430 if(--tc == 0) {
11440 callback(null, self);
1145 }
1146 });
1147 }
1148 } else {
11490 new GridStore(db, names, "w", options).open(function(err, gridStore) {
11500 if(err) return callback(err);
11510 deleteChunks(gridStore, function(err, result) {
11520 if(err) return callback(err);
11530 gridStore.collection(function(err, collection) {
11540 if(err) return callback(err);
11550 collection.remove({'_id':gridStore.fileId}, {safe:true}, function(err, collection) {
11560 callback(err, self);
1157 });
1158 });
1159 });
1160 });
1161 }
1162};
1163
1164/**
1165 * Returns the current chunksize of the file.
1166 *
1167 * @field chunkSize
1168 * @type {Number}
1169 * @getter
1170 * @setter
1171 * @property return number of bytes in the current chunkSize.
1172 */
11731Object.defineProperty(GridStore.prototype, "chunkSize", { enumerable: true
1174 , get: function () {
11750 return this.internalChunkSize;
1176 }
1177 , set: function(value) {
11780 if(!(this.mode[0] == "w" && this.position == 0 && this.uploadDate == null)) {
11790 this.internalChunkSize = this.internalChunkSize;
1180 } else {
11810 this.internalChunkSize = value;
1182 }
1183 }
1184});
1185
1186/**
1187 * The md5 checksum for this file.
1188 *
1189 * @field md5
1190 * @type {Number}
1191 * @getter
1192 * @setter
1193 * @property return this files md5 checksum.
1194 */
11951Object.defineProperty(GridStore.prototype, "md5", { enumerable: true
1196 , get: function () {
11970 return this.internalMd5;
1198 }
1199});
1200
1201/**
1202 * GridStore Streaming methods
1203 * Handles the correct return of the writeable stream status
1204 * @ignore
1205 */
12061Object.defineProperty(GridStore.prototype, "writable", { enumerable: true
1207 , get: function () {
12080 if(this._writeable == null) {
12090 this._writeable = this.mode != null && this.mode.indexOf("w") != -1;
1210 }
1211 // Return the _writeable
12120 return this._writeable;
1213 }
1214 , set: function(value) {
12150 this._writeable = value;
1216 }
1217});
1218
1219/**
1220 * Handles the correct return of the readable stream status
1221 * @ignore
1222 */
12231Object.defineProperty(GridStore.prototype, "readable", { enumerable: true
1224 , get: function () {
12250 if(this._readable == null) {
12260 this._readable = this.mode != null && this.mode.indexOf("r") != -1;
1227 }
12280 return this._readable;
1229 }
1230 , set: function(value) {
12310 this._readable = value;
1232 }
1233});
1234
12351GridStore.prototype.paused;
1236
1237/**
1238 * Handles the correct setting of encoding for the stream
1239 * @ignore
1240 */
12411GridStore.prototype.setEncoding = fs.ReadStream.prototype.setEncoding;
1242
1243/**
1244 * Handles the end events
1245 * @ignore
1246 */
12471GridStore.prototype.end = function end(data) {
12480 var self = this;
1249 // allow queued data to write before closing
12500 if(!this.writable) return;
12510 this.writable = false;
1252
12530 if(data) {
12540 this._q.push(data);
1255 }
1256
12570 this.on('drain', function () {
12580 self.close(function (err) {
12590 if (err) return _error(self, err);
12600 self.emit('close');
1261 });
1262 });
1263
12640 _flush(self);
1265}
1266
1267/**
1268 * Handles the normal writes to gridstore
1269 * @ignore
1270 */
12711var _writeNormal = function(self, data, close, callback) {
1272 // If we have a buffer write it using the writeBuffer method
12730 if(Buffer.isBuffer(data)) {
12740 return writeBuffer(self, data, close, callback);
1275 } else {
1276 // Wrap the string in a buffer and write
12770 return writeBuffer(self, new Buffer(data, 'binary'), close, callback);
1278 }
1279}
1280
1281/**
1282 * Writes some data. This method will work properly only if initialized with mode "w" or "w+".
1283 *
1284 * @param {String|Buffer} data the data to write.
1285 * @param {Boolean} [close] closes this file after writing if set to true.
1286 * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
1287 * @return {null}
1288 * @api public
1289 */
12901GridStore.prototype.write = function write(data, close, callback) {
1291 // If it's a normal write delegate the call
12920 if(typeof close == 'function' || typeof callback == 'function') {
12930 return _writeNormal(this, data, close, callback);
1294 }
1295
1296 // Otherwise it's a stream write
12970 var self = this;
12980 if (!this.writable) {
12990 throw new Error('GridWriteStream is not writable');
1300 }
1301
1302 // queue data until we open.
13030 if (!this._opened) {
1304 // Set up a queue to save data until gridstore object is ready
13050 this._q = [];
13060 _openStream(self);
13070 this._q.push(data);
13080 return false;
1309 }
1310
1311 // Push data to queue
13120 this._q.push(data);
13130 _flush(this);
1314 // Return write successful
13150 return true;
1316}
1317
1318/**
1319 * Handles the destroy part of a stream
1320 * @ignore
1321 */
13221GridStore.prototype.destroy = function destroy() {
1323 // close and do not emit any more events. queued data is not sent.
13240 if(!this.writable) return;
13250 this.readable = false;
13260 if(this.writable) {
13270 this.writable = false;
13280 this._q.length = 0;
13290 this.emit('close');
1330 }
1331}
1332
1333/**
1334 * Handles the destroySoon part of a stream
1335 * @ignore
1336 */
13371GridStore.prototype.destroySoon = function destroySoon() {
1338 // as soon as write queue is drained, destroy.
1339 // may call destroy immediately if no data is queued.
13400 if(!this._q.length) {
13410 return this.destroy();
1342 }
13430 this._destroying = true;
1344}
1345
1346/**
1347 * Handles the pipe part of the stream
1348 * @ignore
1349 */
13501GridStore.prototype.pipe = function(destination, options) {
13510 var self = this;
1352 // Open the gridstore
13530 this.open(function(err, result) {
13540 if(err) _errorRead(self, err);
13550 if(!self.readable) return;
1356 // Set up the pipe
13570 self._pipe(destination, options);
1358 // Emit the stream is open
13590 self.emit('open');
1360 // Read from the stream
13610 _read(self);
1362 })
1363}
1364
1365/**
1366 * Internal module methods
1367 * @ignore
1368 */
13691var _read = function _read(self) {
13700 if (!self.readable || self.paused || self.reading) {
13710 return;
1372 }
1373
13740 self.reading = true;
13750 var stream = self._stream = self.stream();
13760 stream.paused = self.paused;
1377
13780 stream.on('data', function (data) {
13790 if (self._decoder) {
13800 var str = self._decoder.write(data);
13810 if (str.length) self.emit('data', str);
1382 } else {
13830 self.emit('data', data);
1384 }
1385 });
1386
13870 stream.on('end', function (data) {
13880 self.emit('end', data);
1389 });
1390
13910 stream.on('error', function (data) {
13920 _errorRead(self, data);
1393 });
1394
13950 stream.on('close', function (data) {
13960 self.emit('close', data);
1397 });
1398
13990 self.pause = function () {
1400 // native doesn't always pause.
1401 // bypass its pause() method to hack it
14020 self.paused = stream.paused = true;
1403 }
1404
14050 self.resume = function () {
14060 if(!self.paused) return;
1407
14080 self.paused = false;
14090 stream.resume();
14100 self.readable = stream.readable;
1411 }
1412
14130 self.destroy = function () {
14140 self.readable = false;
14150 stream.destroy();
1416 }
1417}
1418
1419/**
1420 * pause
1421 * @ignore
1422 */
14231GridStore.prototype.pause = function pause () {
1424 // Overridden when the GridStore opens.
14250 this.paused = true;
1426}
1427
1428/**
1429 * resume
1430 * @ignore
1431 */
14321GridStore.prototype.resume = function resume () {
1433 // Overridden when the GridStore opens.
14340 this.paused = false;
1435}
1436
1437/**
1438 * Internal module methods
1439 * @ignore
1440 */
14411var _flush = function _flush(self, _force) {
14420 if (!self._opened) return;
14430 if (!_force && self._flushing) return;
14440 self._flushing = true;
1445
1446 // write the entire q to gridfs
14470 if (!self._q.length) {
14480 self._flushing = false;
14490 self.emit('drain');
1450
14510 if(self._destroying) {
14520 self.destroy();
1453 }
14540 return;
1455 }
1456
14570 self.write(self._q.shift(), function (err, store) {
14580 if (err) return _error(self, err);
14590 self.emit('progress', store.position);
14600 _flush(self, true);
1461 });
1462}
1463
14641var _openStream = function _openStream (self) {
14650 if(self._opening == true) return;
14660 self._opening = true;
1467
1468 // Open the store
14690 self.open(function (err, gridstore) {
14700 if (err) return _error(self, err);
14710 self._opened = true;
14720 self.emit('open');
14730 _flush(self);
1474 });
1475}
1476
14771var _error = function _error(self, err) {
14780 self.destroy();
14790 self.emit('error', err);
1480}
1481
14821var _errorRead = function _errorRead (self, err) {
14830 self.readable = false;
14840 self.emit('error', err);
1485}
1486
1487/**
1488 * @ignore
1489 */
14901var _hasWriteConcern = function(errorOptions) {
14910 return errorOptions == true
1492 || errorOptions.w > 0
1493 || errorOptions.w == 'majority'
1494 || errorOptions.j == true
1495 || errorOptions.journal == true
1496 || errorOptions.fsync == true
1497}
1498
1499/**
1500 * @ignore
1501 */
15021var _setWriteConcernHash = function(options) {
15030 var finalOptions = {};
15040 if(options.w != null) finalOptions.w = options.w;
15050 if(options.journal == true) finalOptions.j = options.journal;
15060 if(options.j == true) finalOptions.j = options.j;
15070 if(options.fsync == true) finalOptions.fsync = options.fsync;
15080 if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout;
15090 return finalOptions;
1510}
1511
1512/**
1513 * @ignore
1514 */
15151var _getWriteConcern = function(self, options, callback) {
1516 // Final options
15170 var finalOptions = {w:1};
15180 options = options || {};
1519 // Local options verification
15200 if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') {
15210 finalOptions = _setWriteConcernHash(options);
15220 } else if(typeof options.safe == "boolean") {
15230 finalOptions = {w: (options.safe ? 1 : 0)};
15240 } else if(options.safe != null && typeof options.safe == 'object') {
15250 finalOptions = _setWriteConcernHash(options.safe);
15260 } else if(self.db.safe.w != null || typeof self.db.safe.j == 'boolean' || typeof self.db.safe.journal == 'boolean' || typeof self.db.safe.fsync == 'boolean') {
15270 finalOptions = _setWriteConcernHash(self.db.safe);
15280 } else if(self.db.options.w != null || typeof self.db.options.j == 'boolean' || typeof self.db.options.journal == 'boolean' || typeof self.db.options.fsync == 'boolean') {
15290 finalOptions = _setWriteConcernHash(self.db.options);
15300 } else if(typeof self.db.safe == "boolean") {
15310 finalOptions = {w: (self.db.safe ? 1 : 0)};
1532 }
1533
1534 // Ensure we don't have an invalid combination of write concerns
15350 if(finalOptions.w < 1
15360 && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowlegement using w < 1 cannot be combined with journal:true or fsync:true");
1537
1538 // Return the options
15390 return finalOptions;
1540}
1541
1542/**
1543 * @ignore
1544 * @api private
1545 */
15461exports.GridStore = GridStore;
1547

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/gridfs/readstream.js

12%
89
11
78
LineHitsSource
11var Stream = require('stream').Stream,
2 timers = require('timers'),
3 util = require('util');
4
5// Set processor, setImmediate if 0.10 otherwise nextTick
61var processor = require('../utils').processor();
7
8/**
9 * ReadStream
10 *
11 * Returns a stream interface for the **file**.
12 *
13 * Events
14 * - **data** {function(item) {}} the data event triggers when a document is ready.
15 * - **end** {function() {}} the end event triggers when there is no more documents available.
16 * - **close** {function() {}} the close event triggers when the stream is closed.
17 * - **error** {function(err) {}} the error event triggers if an error happens.
18 *
19 * @class Represents a GridFS File Stream.
20 * @param {Boolean} autoclose automatically close file when the stream reaches the end.
21 * @param {GridStore} cursor a cursor object that the stream wraps.
22 * @return {ReadStream}
23 */
241function ReadStream(autoclose, gstore) {
250 if (!(this instanceof ReadStream)) return new ReadStream(autoclose, gstore);
260 Stream.call(this);
27
280 this.autoclose = !!autoclose;
290 this.gstore = gstore;
30
310 this.finalLength = gstore.length - gstore.position;
320 this.completedLength = 0;
330 this.currentChunkNumber = gstore.currentChunk.chunkNumber;
34
350 this.paused = false;
360 this.readable = true;
370 this.pendingChunk = null;
380 this.executing = false;
390 this.destroyed = false;
40
41 // Calculate the number of chunks
420 this.numberOfChunks = Math.ceil(gstore.length/gstore.chunkSize);
43
44 // This seek start position inside the current chunk
450 this.seekStartPosition = gstore.position - (this.currentChunkNumber * gstore.chunkSize);
46
470 var self = this;
480 processor(function() {
490 self._execute();
50 });
51};
52
53/**
54 * Inherit from Stream
55 * @ignore
56 * @api private
57 */
581ReadStream.prototype.__proto__ = Stream.prototype;
59
60/**
61 * Flag stating whether or not this stream is readable.
62 */
631ReadStream.prototype.readable;
64
65/**
66 * Flag stating whether or not this stream is paused.
67 */
681ReadStream.prototype.paused;
69
70/**
71 * @ignore
72 * @api private
73 */
741ReadStream.prototype._execute = function() {
750 if(this.paused === true || this.readable === false) {
760 return;
77 }
78
790 var gstore = this.gstore;
800 var self = this;
81 // Set that we are executing
820 this.executing = true;
83
840 var last = false;
850 var toRead = 0;
86
870 if(gstore.currentChunk.chunkNumber >= (this.numberOfChunks - 1)) {
880 self.executing = false;
890 last = true;
90 }
91
92 // Data setup
930 var data = null;
94
95 // Read a slice (with seek set if none)
960 if(this.seekStartPosition > 0 && (gstore.currentChunk.length() - this.seekStartPosition) > 0) {
970 data = gstore.currentChunk.readSlice(gstore.currentChunk.length() - this.seekStartPosition);
980 this.seekStartPosition = 0;
99 } else {
1000 data = gstore.currentChunk.readSlice(gstore.currentChunk.length());
101 }
102
103 // Return the data
1040 if(data != null && gstore.currentChunk.chunkNumber == self.currentChunkNumber) {
1050 self.currentChunkNumber = self.currentChunkNumber + 1;
1060 self.completedLength += data.length;
1070 self.pendingChunk = null;
1080 self.emit("data", data);
109 }
110
1110 if(last === true) {
1120 self.readable = false;
1130 self.emit("end");
114
1150 if(self.autoclose === true) {
1160 if(gstore.mode[0] == "w") {
1170 gstore.close(function(err, doc) {
1180 if (err) {
1190 console.log("############################## 0")
1200 self.emit("error", err);
1210 return;
122 }
1230 self.readable = false;
1240 self.destroyed = true;
1250 self.emit("close", doc);
126 });
127 } else {
1280 self.readable = false;
1290 self.destroyed = true;
1300 self.emit("close");
131 }
132 }
133 } else {
1340 gstore._nthChunk(gstore.currentChunk.chunkNumber + 1, function(err, chunk) {
1350 if(err) {
1360 self.readable = false;
1370 if(self.listeners("error").length > 0)
1380 self.emit("error", err);
1390 self.executing = false;
1400 return;
141 }
142
1430 self.pendingChunk = chunk;
1440 if(self.paused === true) {
1450 self.executing = false;
1460 return;
147 }
148
1490 gstore.currentChunk = self.pendingChunk;
1500 self._execute();
151 });
152 }
153};
154
155/**
156 * Pauses this stream, then no farther events will be fired.
157 *
158 * @ignore
159 * @api public
160 */
1611ReadStream.prototype.pause = function() {
1620 if(!this.executing) {
1630 this.paused = true;
164 }
165};
166
167/**
168 * Destroys the stream, then no farther events will be fired.
169 *
170 * @ignore
171 * @api public
172 */
1731ReadStream.prototype.destroy = function() {
1740 if(this.destroyed) return;
1750 this.destroyed = true;
1760 this.readable = false;
177 // Emit close event
1780 this.emit("close");
179};
180
181/**
182 * Resumes this stream.
183 *
184 * @ignore
185 * @api public
186 */
1871ReadStream.prototype.resume = function() {
1880 if(this.paused === false || !this.readable) {
1890 return;
190 }
191
1920 this.paused = false;
1930 var self = this;
1940 processor(function() {
1950 self._execute();
196 });
197};
198
1991exports.ReadStream = ReadStream;
200

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/index.js

96%
30
29
1
LineHitsSource
11try {
21 exports.BSONPure = require('bson').BSONPure;
31 exports.BSONNative = require('bson').BSONNative;
4} catch(err) {
5 // do nothing
6}
7
8// export the driver version
91exports.version = require('../../package').version;
10
111[ 'commands/base_command'
12 , 'admin'
13 , 'collection'
14 , 'connection/read_preference'
15 , 'connection/connection'
16 , 'connection/server'
17 , 'connection/mongos'
18 , 'connection/repl_set/repl_set'
19 , 'mongo_client'
20 , 'cursor'
21 , 'db'
22 , 'mongo_client'
23 , 'gridfs/grid'
24 , 'gridfs/chunk'
25 , 'gridfs/gridstore'].forEach(function (path) {
2615 var module = require('./' + path);
2715 for (var i in module) {
2816 exports[i] = module[i];
29 }
30});
31
32// backwards compat
331exports.ReplSetServers = exports.ReplSet;
34// Add BSON Classes
351exports.Binary = require('bson').Binary;
361exports.Code = require('bson').Code;
371exports.DBRef = require('bson').DBRef;
381exports.Double = require('bson').Double;
391exports.Long = require('bson').Long;
401exports.MinKey = require('bson').MinKey;
411exports.MaxKey = require('bson').MaxKey;
421exports.ObjectID = require('bson').ObjectID;
431exports.Symbol = require('bson').Symbol;
441exports.Timestamp = require('bson').Timestamp;
45// Add BSON Parser
461exports.BSON = require('bson').BSONPure.BSON;
47
48// Get the Db object
491var Db = require('./db').Db;
50// Set up the connect function
511var connect = Db.connect;
521var obj = connect;
53// Map all values to the exports value
541for(var name in exports) {
5530 obj[name] = exports[name];
56}
57
58// Add the pure and native backward compatible functions
591exports.pure = exports.native = function() {
600 return obj;
61}
62
63// Map all values to the exports value
641for(var name in exports) {
6532 connect[name] = exports[name];
66}
67
68// Set our exports to be the connect function
691module.exports = connect;
70

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/mongo_client.js

6%
172
11
161
LineHitsSource
11var Db = require('./db').Db
2 , Server = require('./connection/server').Server
3 , Mongos = require('./connection/mongos').Mongos
4 , ReplSet = require('./connection/repl_set/repl_set').ReplSet
5 , ReadPreference = require('./connection/read_preference').ReadPreference
6 , inherits = require('util').inherits
7 , EventEmitter = require('events').EventEmitter
8 , parse = require('./connection/url_parser').parse;
9
10/**
11 * Create a new MongoClient instance.
12 *
13 * Options
14 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
15 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
16 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
17 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
18 * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
19 * - **native_parser** {Boolean, default:false}, use c++ bson parser.
20 * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client.
21 * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
22 * - **serializeFunctions** {Boolean, default:false}, serialize functions.
23 * - **raw** {Boolean, default:false}, peform operations using raw bson buffers.
24 * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution.
25 * - **retryMiliSeconds** {Number, default:5000}, number of miliseconds between retries.
26 * - **numberOfRetries** {Number, default:5}, number of retries off connection.
27 * - **bufferMaxEntries** {Boolean, default: -1}, sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited
28 *
29 * Deprecated Options
30 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
31 *
32 * @class Represents a MongoClient
33 * @param {Object} serverConfig server config object.
34 * @param {Object} [options] additional options for the collection.
35 */
361function MongoClient(serverConfig, options) {
370 if(serverConfig != null) {
380 options = options == null ? {} : options;
39 // If no write concern is set set the default to w:1
400 if(options != null && !options.journal && !options.w && !options.fsync) {
410 options.w = 1;
42 }
43
44 // The internal db instance we are wrapping
450 this._db = new Db('test', serverConfig, options);
46 }
47}
48
49/**
50 * @ignore
51 */
521inherits(MongoClient, EventEmitter);
53
54/**
55 * Connect to MongoDB using a url as documented at
56 *
57 * docs.mongodb.org/manual/reference/connection-string/
58 *
59 * Options
60 * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication
61 * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor**
62 * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor**
63 * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor**
64 * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor**
65 *
66 * @param {String} url connection url for MongoDB.
67 * @param {Object} [options] optional options for insert command
68 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured.
69 * @return {null}
70 * @api public
71 */
721MongoClient.prototype.connect = function(url, options, callback) {
730 var self = this;
74
750 if(typeof options == 'function') {
760 callback = options;
770 options = {};
78 }
79
800 MongoClient.connect(url, options, function(err, db) {
810 if(err) return callback(err, db);
82 // Store internal db instance reference
830 self._db = db;
84 // Emit open and perform callback
850 self.emit("open", err, db);
860 callback(err, db);
87 });
88}
89
90/**
91 * Initialize the database connection.
92 *
93 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the connected mongoclient or null if an error occured.
94 * @return {null}
95 * @api public
96 */
971MongoClient.prototype.open = function(callback) {
98 // Self reference
990 var self = this;
100 // Open the db
1010 this._db.open(function(err, db) {
1020 if(err) return callback(err, null);
103 // Emit open event
1040 self.emit("open", err, db);
105 // Callback
1060 callback(null, self);
107 })
108}
109
110/**
111 * Close the current db connection, including all the child db instances. Emits close event if no callback is provided.
112 *
113 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the close method or null if an error occured.
114 * @return {null}
115 * @api public
116 */
1171MongoClient.prototype.close = function(callback) {
1180 this._db.close(callback);
119}
120
121/**
122 * Create a new Db instance sharing the current socket connections.
123 *
124 * @param {String} dbName the name of the database we want to use.
125 * @return {Db} a db instance using the new database.
126 * @api public
127 */
1281MongoClient.prototype.db = function(dbName) {
1290 return this._db.db(dbName);
130}
131
132/**
133 * Connect to MongoDB using a url as documented at
134 *
135 * docs.mongodb.org/manual/reference/connection-string/
136 *
137 * Options
138 * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication
139 * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor**
140 * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor**
141 * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor**
142 * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor**
143 *
144 * @param {String} url connection url for MongoDB.
145 * @param {Object} [options] optional options for insert command
146 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured.
147 * @return {null}
148 * @api public
149 */
1501MongoClient.connect = function(url, options, callback) {
1510 var args = Array.prototype.slice.call(arguments, 1);
1520 callback = typeof args[args.length - 1] == 'function' ? args.pop() : null;
1530 options = args.length ? args.shift() : null;
1540 options = options || {};
155
156 // Set default empty server options
1570 var serverOptions = options.server || {};
1580 var mongosOptions = options.mongos || {};
1590 var replSetServersOptions = options.replSet || options.replSetServers || {};
1600 var dbOptions = options.db || {};
161
162 // If callback is null throw an exception
1630 if(callback == null)
1640 throw new Error("no callback function provided");
165
166 // Parse the string
1670 var object = parse(url, options);
168 // Merge in any options for db in options object
1690 if(dbOptions) {
1700 for(var name in dbOptions) object.db_options[name] = dbOptions[name];
171 }
172
173 // Added the url to the options
1740 object.db_options.url = url;
175
176 // Merge in any options for server in options object
1770 if(serverOptions) {
1780 for(var name in serverOptions) object.server_options[name] = serverOptions[name];
179 }
180
181 // Merge in any replicaset server options
1820 if(replSetServersOptions) {
1830 for(var name in replSetServersOptions) object.rs_options[name] = replSetServersOptions[name];
184 }
185
186 // Merge in any replicaset server options
1870 if(mongosOptions) {
1880 for(var name in mongosOptions) object.mongos_options[name] = mongosOptions[name];
189 }
190
191 // We need to ensure that the list of servers are only either direct members or mongos
192 // they cannot be a mix of monogs and mongod's
1930 var totalNumberOfServers = object.servers.length;
1940 var totalNumberOfMongosServers = 0;
1950 var totalNumberOfMongodServers = 0;
1960 var serverConfig = null;
1970 var errorServers = {};
198
199 // Failure modes
2000 if(object.servers.length == 0) throw new Error("connection string must contain at least one seed host");
201
202 // If we have no db setting for the native parser try to set the c++ one first
2030 object.db_options.native_parser = _setNativeParser(object.db_options);
204 // If no auto_reconnect is set, set it to true as default for single servers
2050 if(typeof object.server_options.auto_reconnect != 'boolean') {
2060 object.server_options.auto_reconnect = true;
207 }
208
209 // If we have more than a server, it could be replicaset or mongos list
210 // need to verify that it's one or the other and fail if it's a mix
211 // Connect to all servers and run ismaster
2120 for(var i = 0; i < object.servers.length; i++) {
213 // Set up socket options
2140 var _server_options = {
215 poolSize:1
216 , socketOptions: {
217 connectTimeoutMS:30000
218 , socketTimeoutMS: 30000
219 }
220 , auto_reconnect:false};
221
222 // Ensure we have ssl setup for the servers
2230 if(object.rs_options.ssl) {
2240 _server_options.ssl = object.rs_options.ssl;
2250 _server_options.sslValidate = object.rs_options.sslValidate;
2260 _server_options.sslCA = object.rs_options.sslCA;
2270 _server_options.sslCert = object.rs_options.sslCert;
2280 _server_options.sslKey = object.rs_options.sslKey;
2290 _server_options.sslPass = object.rs_options.sslPass;
2300 } else if(object.server_options.ssl) {
2310 _server_options.ssl = object.server_options.ssl;
2320 _server_options.sslValidate = object.server_options.sslValidate;
2330 _server_options.sslCA = object.server_options.sslCA;
2340 _server_options.sslCert = object.server_options.sslCert;
2350 _server_options.sslKey = object.server_options.sslKey;
2360 _server_options.sslPass = object.server_options.sslPass;
237 }
238
239 // Set up the Server object
2400 var _server = object.servers[i].domain_socket
241 ? new Server(object.servers[i].domain_socket, _server_options)
242 : new Server(object.servers[i].host, object.servers[i].port, _server_options);
243
2440 var connectFunction = function(__server) {
245 // Attempt connect
2460 new Db(object.dbName, __server, {safe:false, native_parser:false}).open(function(err, db) {
247 // Update number of servers
2480 totalNumberOfServers = totalNumberOfServers - 1;
249 // If no error do the correct checks
2500 if(!err) {
251 // Close the connection
2520 db.close(true);
2530 var isMasterDoc = db.serverConfig.isMasterDoc;
254 // Check what type of server we have
2550 if(isMasterDoc.setName) totalNumberOfMongodServers++;
2560 if(isMasterDoc.msg && isMasterDoc.msg == "isdbgrid") totalNumberOfMongosServers++;
257 } else {
2580 errorServers[__server.host + ":" + __server.port] = __server;
259 }
260
2610 if(totalNumberOfServers == 0) {
262 // If we have a mix of mongod and mongos, throw an error
2630 if(totalNumberOfMongosServers > 0 && totalNumberOfMongodServers > 0) {
2640 return process.nextTick(function() {
2650 try {
2660 callback(new Error("cannot combine a list of replicaset seeds and mongos seeds"));
267 } catch (err) {
2680 if(db) db.close();
2690 throw err
270 }
271 })
272 }
273
2740 if(totalNumberOfMongodServers == 0 && object.servers.length == 1) {
2750 var obj = object.servers[0];
2760 serverConfig = obj.domain_socket ?
277 new Server(obj.domain_socket, object.server_options)
278 : new Server(obj.host, obj.port, object.server_options);
2790 } else if(totalNumberOfMongodServers > 0 || totalNumberOfMongosServers > 0) {
2800 var finalServers = object.servers
281 .filter(function(serverObj) {
2820 return errorServers[serverObj.host + ":" + serverObj.port] == null;
283 })
284 .map(function(serverObj) {
2850 return new Server(serverObj.host, serverObj.port, object.server_options);
286 });
287 // Clean out any error servers
2880 errorServers = {};
289 // Set up the final configuration
2900 if(totalNumberOfMongodServers > 0) {
2910 serverConfig = new ReplSet(finalServers, object.rs_options);
292 } else {
2930 serverConfig = new Mongos(finalServers, object.mongos_options);
294 }
295 }
296
2970 if(serverConfig == null) {
2980 return process.nextTick(function() {
2990 try {
3000 callback(new Error("Could not locate any valid servers in initial seed list"));
301 } catch (err) {
3020 if(db) db.close();
3030 throw err
304 }
305 });
306 }
307 // Ensure no firing off open event before we are ready
3080 serverConfig.emitOpen = false;
309 // Set up all options etc and connect to the database
3100 _finishConnecting(serverConfig, object, options, callback)
311 }
312 });
313 }
314
315 // Wrap the context of the call
3160 connectFunction(_server);
317 }
318}
319
3201var _setNativeParser = function(db_options) {
3210 if(typeof db_options.native_parser == 'boolean') return db_options.native_parser;
322
3230 try {
3240 require('bson').BSONNative.BSON;
3250 return true;
326 } catch(err) {
3270 return false;
328 }
329}
330
3311var _finishConnecting = function(serverConfig, object, options, callback) {
332 // Safe settings
3330 var safe = {};
334 // Build the safe parameter if needed
3350 if(object.db_options.journal) safe.j = object.db_options.journal;
3360 if(object.db_options.w) safe.w = object.db_options.w;
3370 if(object.db_options.fsync) safe.fsync = object.db_options.fsync;
3380 if(object.db_options.wtimeoutMS) safe.wtimeout = object.db_options.wtimeoutMS;
339
340 // If we have a read Preference set
3410 if(object.db_options.read_preference) {
3420 var readPreference = new ReadPreference(object.db_options.read_preference);
343 // If we have the tags set up
3440 if(object.db_options.read_preference_tags)
3450 readPreference = new ReadPreference(object.db_options.read_preference, object.db_options.read_preference_tags);
346 // Add the read preference
3470 object.db_options.readPreference = readPreference;
348 }
349
350 // No safe mode if no keys
3510 if(Object.keys(safe).length == 0) safe = false;
352
353 // Add the safe object
3540 object.db_options.safe = safe;
355
356 // Get the socketTimeoutMS
3570 var socketTimeoutMS = object.server_options.socketOptions.socketTimeoutMS || 0;
358
359 // If we have a replset, override with replicaset socket timeout option if available
3600 if(serverConfig instanceof ReplSet) {
3610 socketTimeoutMS = object.rs_options.socketOptions.socketTimeoutMS || socketTimeoutMS;
362 }
363
364 // Set socketTimeout to the same as the connectTimeoutMS or 30 sec
3650 serverConfig.connectTimeoutMS = serverConfig.connectTimeoutMS || 30000;
3660 serverConfig.socketTimeoutMS = serverConfig.connectTimeoutMS;
367
368 // Set up the db options
3690 var db = new Db(object.dbName, serverConfig, object.db_options);
370 // Open the db
3710 db.open(function(err, db){
3720 if(err) {
3730 return process.nextTick(function() {
3740 try {
3750 callback(err, null);
376 } catch (err) {
3770 if(db) db.close();
3780 throw err
379 }
380 });
381 }
382
383 // Reset the socket timeout
3840 serverConfig.socketTimeoutMS = socketTimeoutMS || 0;
385
386 // Set the provided write concern or fall back to w:1 as default
3870 if(db.options !== null && !db.options.safe && !db.options.journal
388 && !db.options.w && !db.options.fsync && typeof db.options.w != 'number'
389 && (db.options.safe == false && object.db_options.url.indexOf("safe=") == -1)) {
3900 db.options.w = 1;
391 }
392
3930 if(err == null && object.auth){
394 // What db to authenticate against
3950 var authentication_db = db;
3960 if(object.db_options && object.db_options.authSource) {
3970 authentication_db = db.db(object.db_options.authSource);
398 }
399
400 // Build options object
4010 var options = {};
4020 if(object.db_options.authMechanism) options.authMechanism = object.db_options.authMechanism;
4030 if(object.db_options.gssapiServiceName) options.gssapiServiceName = object.db_options.gssapiServiceName;
404
405 // Authenticate
4060 authentication_db.authenticate(object.auth.user, object.auth.password, options, function(err, success){
4070 if(success){
4080 process.nextTick(function() {
4090 try {
4100 callback(null, db);
411 } catch (err) {
4120 if(db) db.close();
4130 throw err
414 }
415 });
416 } else {
4170 if(db) db.close();
4180 process.nextTick(function() {
4190 try {
4200 callback(err ? err : new Error('Could not authenticate user ' + auth[0]), null);
421 } catch (err) {
4220 if(db) db.close();
4230 throw err
424 }
425 });
426 }
427 });
428 } else {
4290 process.nextTick(function() {
4300 try {
4310 callback(err, db);
432 } catch (err) {
4330 if(db) db.close();
4340 throw err
435 }
436 })
437 }
438 });
439}
440
4411exports.MongoClient = MongoClient;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js

17%
41
7
34
LineHitsSource
11var Long = require('bson').Long
2 , timers = require('timers');
3
4// Set processor, setImmediate if 0.10 otherwise nextTick
51var processor = require('../utils').processor();
6
7/**
8 Reply message from mongo db
9**/
101var MongoReply = exports.MongoReply = function() {
110 this.documents = [];
120 this.index = 0;
13};
14
151MongoReply.prototype.parseHeader = function(binary_reply, bson) {
16 // Unpack the standard header first
170 this.messageLength = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
180 this.index = this.index + 4;
19 // Fetch the request id for this reply
200 this.requestId = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
210 this.index = this.index + 4;
22 // Fetch the id of the request that triggered the response
230 this.responseTo = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
24 // Skip op-code field
250 this.index = this.index + 4 + 4;
26 // Unpack the reply message
270 this.responseFlag = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
280 this.index = this.index + 4;
29 // Unpack the cursor id (a 64 bit long integer)
300 var low_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
310 this.index = this.index + 4;
320 var high_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
330 this.index = this.index + 4;
340 this.cursorId = new Long(low_bits, high_bits);
35 // Unpack the starting from
360 this.startingFrom = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
370 this.index = this.index + 4;
38 // Unpack the number of objects returned
390 this.numberReturned = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
400 this.index = this.index + 4;
41}
42
431MongoReply.prototype.parseBody = function(binary_reply, bson, raw, callback) {
440 raw = raw == null ? false : raw;
45
460 try {
47 // Let's unpack all the bson documents, deserialize them and store them
480 for(var object_index = 0; object_index < this.numberReturned; object_index++) {
490 var _options = {promoteLongs: bson.promoteLongs};
50
51 // Read the size of the bson object
520 var bsonObjectSize = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
53
54 // If we are storing the raw responses to pipe straight through
550 if(raw) {
56 // Deserialize the object and add to the documents array
570 this.documents.push(binary_reply.slice(this.index, this.index + bsonObjectSize));
58 } else {
59 // Deserialize the object and add to the documents array
600 this.documents.push(bson.deserialize(binary_reply.slice(this.index, this.index + bsonObjectSize), _options));
61 }
62
63 // Adjust binary index to point to next block of binary bson data
640 this.index = this.index + bsonObjectSize;
65 }
66
67 // No error return
680 callback(null);
69 } catch(err) {
700 return callback(err);
71 }
72}
73
741MongoReply.prototype.is_error = function(){
750 if(this.documents.length == 1) {
760 return this.documents[0].ok == 1 ? false : true;
77 }
780 return false;
79};
80
811MongoReply.prototype.error_message = function() {
820 return this.documents.length == 1 && this.documents[0].ok == 1 ? '' : this.documents[0].errmsg;
83};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/scope.js

4%
88
4
84
LineHitsSource
11var Cursor2 = require('./cursor').Cursor
2 , Readable = require('stream').Readable
3 , utils = require('./utils')
4 , inherits = require('util').inherits;
5
61var Cursor = function Cursor(_scope_options, _cursor) {
7 //
8 // Backward compatible methods
90 this.toArray = function(callback) {
100 return _cursor.toArray(callback);
11 }
12
130 this.each = function(callback) {
140 return _cursor.each(callback);
15 }
16
170 this.next = function(callback) {
180 this.nextObject(callback);
19 }
20
210 this.nextObject = function(callback) {
220 return _cursor.nextObject(callback);
23 }
24
250 this.setReadPreference = function(readPreference, callback) {
260 _scope_options.readPreference = {readPreference: readPreference};
270 _cursor.setReadPreference(readPreference, callback);
280 return this;
29 }
30
310 this.batchSize = function(batchSize, callback) {
320 _scope_options.batchSize = batchSize;
330 _cursor.batchSize(_scope_options.batchSize, callback);
340 return this;
35 }
36
370 this.count = function(applySkipLimit, callback) {
380 return _cursor.count(applySkipLimit, callback);
39 }
40
410 this.stream = function(options) {
420 return _cursor.stream(options);
43 }
44
450 this.close = function(callback) {
460 return _cursor.close(callback);
47 }
48
490 this.explain = function(callback) {
500 return _cursor.explain(callback);
51 }
52
530 this.isClosed = function(callback) {
540 return _cursor.isClosed();
55 }
56
570 this.rewind = function() {
580 return _cursor.rewind();
59 }
60
61 // Internal methods
620 this.limit = function(limit, callback) {
630 _cursor.limit(limit, callback);
640 _scope_options.limit = limit;
650 return this;
66 }
67
680 this.skip = function(skip, callback) {
690 _cursor.skip(skip, callback);
700 _scope_options.skip = skip;
710 return this;
72 }
73
740 this.hint = function(hint) {
750 _scope_options.hint = hint;
760 _cursor.hint = _scope_options.hint;
770 return this;
78 }
79
800 this.maxTimeMS = function(maxTimeMS) {
810 _cursor.maxTimeMS(maxTimeMS)
820 _scope_options.maxTimeMS = maxTimeMS;
830 return this;
84 },
85
86 this.sort = function(keyOrList, direction, callback) {
870 _cursor.sort(keyOrList, direction, callback);
880 _scope_options.sort = keyOrList;
890 return this;
90 },
91
92 this.fields = function(fields) {
930 _fields = fields;
940 _cursor.fields = _fields;
950 return this;
96 }
97
98 //
99 // Backward compatible settings
1000 Object.defineProperty(this, "timeout", {
101 get: function() {
1020 return _cursor.timeout;
103 }
104 });
105
1060 Object.defineProperty(this, "read", {
107 get: function() {
1080 return _cursor.read;
109 }
110 });
111
1120 Object.defineProperty(this, "items", {
113 get: function() {
1140 return _cursor.items;
115 }
116 });
117}
118
1191var Scope = function(collection, _selector, _fields, _scope_options) {
1200 var self = this;
121
122 // Ensure we have at least an empty cursor options object
1230 _scope_options = _scope_options || {};
1240 var _write_concern = _scope_options.write_concern || null;
125
126 // Ensure default read preference
1270 if(!_scope_options.readPreference) _scope_options.readPreference = {readPreference: 'primary'};
128
129 // Set up the cursor
1300 var _cursor = new Cursor2(
131 collection.db, collection, _selector
132 , _fields, _scope_options
133 );
134
135 // Write branch options
1360 var writeOptions = {
137 insert: function(documents, callback) {
138 // Merge together options
1390 var options = _write_concern || {};
140 // Execute insert
1410 collection.insert(documents, options, callback);
142 },
143
144 save: function(document, callback) {
145 // Merge together options
1460 var save_options = _write_concern || {};
147 // Execute save
1480 collection.save(document, save_options, function(err, result) {
1490 if(typeof result == 'number' && result == 1) {
1500 return callback(null, document);
151 }
152
1530 return callback(null, document);
154 });
155 },
156
157 find: function(selector) {
1580 _selector = selector;
1590 return writeOptions;
160 },
161
162 //
163 // Update is implicit multiple document update
164 update: function(operations, callback) {
165 // Merge together options
1660 var update_options = _write_concern || {};
167
168 // Set up options, multi is default operation
1690 update_options.multi = _scope_options.multi ? _scope_options.multi : true;
1700 if(_scope_options.upsert) update_options.upsert = _scope_options.upsert;
171
172 // Execute options
1730 collection.update(_selector, operations, update_options, function(err, result, obj) {
1740 callback(err, obj);
175 });
176 },
177 }
178
179 // Set write concern
1800 this.withWriteConcern = function(write_concern) {
181 // Save the current write concern to the Scope
1820 _scope_options.write_concern = write_concern;
1830 _write_concern = write_concern;
184 // Only allow legal options
1850 return writeOptions;
186 }
187
188 // Start find
1890 this.find = function(selector, options) {
190 // Save the current selector
1910 _selector = selector;
192 // Set the cursor
1930 _cursor.selector = selector;
194 // Return only legal read options
1950 return new Cursor(_scope_options, _cursor);
196 }
197}
198
1991exports.Scope = Scope;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/lib/mongodb/utils.js

26%
84
22
62
LineHitsSource
11var timers = require('timers');
2
3/**
4 * Sort functions, Normalize and prepare sort parameters
5 */
61var formatSortValue = exports.formatSortValue = function(sortDirection) {
70 var value = ("" + sortDirection).toLowerCase();
8
90 switch (value) {
10 case 'ascending':
11 case 'asc':
12 case '1':
130 return 1;
14 case 'descending':
15 case 'desc':
16 case '-1':
170 return -1;
18 default:
190 throw new Error("Illegal sort clause, must be of the form "
20 + "[['field1', '(ascending|descending)'], "
21 + "['field2', '(ascending|descending)']]");
22 }
23};
24
251var formattedOrderClause = exports.formattedOrderClause = function(sortValue) {
260 var orderBy = {};
27
280 if (Array.isArray(sortValue)) {
290 for(var i = 0; i < sortValue.length; i++) {
300 if(sortValue[i].constructor == String) {
310 orderBy[sortValue[i]] = 1;
32 } else {
330 orderBy[sortValue[i][0]] = formatSortValue(sortValue[i][1]);
34 }
35 }
360 } else if(Object.prototype.toString.call(sortValue) === '[object Object]') {
370 orderBy = sortValue;
380 } else if (sortValue.constructor == String) {
390 orderBy[sortValue] = 1;
40 } else {
410 throw new Error("Illegal sort clause, must be of the form " +
42 "[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]");
43 }
44
450 return orderBy;
46};
47
481exports.encodeInt = function(value) {
490 var buffer = new Buffer(4);
500 buffer[3] = (value >> 24) & 0xff;
510 buffer[2] = (value >> 16) & 0xff;
520 buffer[1] = (value >> 8) & 0xff;
530 buffer[0] = value & 0xff;
540 return buffer;
55}
56
571exports.encodeIntInPlace = function(value, buffer, index) {
580 buffer[index + 3] = (value >> 24) & 0xff;
590 buffer[index + 2] = (value >> 16) & 0xff;
600 buffer[index + 1] = (value >> 8) & 0xff;
610 buffer[index] = value & 0xff;
62}
63
641exports.encodeCString = function(string) {
650 var buf = new Buffer(string, 'utf8');
660 return [buf, new Buffer([0])];
67}
68
691exports.decodeUInt32 = function(array, index) {
700 return array[index] | array[index + 1] << 8 | array[index + 2] << 16 | array[index + 3] << 24;
71}
72
73// Decode the int
741exports.decodeUInt8 = function(array, index) {
750 return array[index];
76}
77
78/**
79 * Context insensitive type checks
80 */
81
821var toString = Object.prototype.toString;
83
841exports.isObject = function (arg) {
850 return '[object Object]' == toString.call(arg)
86}
87
881exports.isArray = function (arg) {
890 return Array.isArray(arg) ||
90 'object' == typeof arg && '[object Array]' == toString.call(arg)
91}
92
931exports.isDate = function (arg) {
940 return 'object' == typeof arg && '[object Date]' == toString.call(arg)
95}
96
971exports.isRegExp = function (arg) {
980 return 'object' == typeof arg && '[object RegExp]' == toString.call(arg)
99}
100
101/**
102 * Wrap a Mongo error document in an Error instance
103 * @ignore
104 * @api private
105 */
1061var toError = function(error) {
1070 if (error instanceof Error) return error;
108
1090 var msg = error.err || error.errmsg || error.errMessage || error;
1100 var e = new Error(msg);
1110 e.name = 'MongoError';
112
113 // Get all object keys
1140 var keys = typeof error == 'object'
115 ? Object.keys(error)
116 : [];
117
1180 for(var i = 0; i < keys.length; i++) {
1190 e[keys[i]] = error[keys[i]];
120 }
121
1220 return e;
123}
1241exports.toError = toError;
125
126/**
127 * Convert a single level object to an array
128 * @ignore
129 * @api private
130 */
1311exports.objectToArray = function(object) {
1320 var list = [];
133
1340 for(var name in object) {
1350 list.push(object[name])
136 }
137
1380 return list;
139}
140
141/**
142 * Handle single command document return
143 * @ignore
144 * @api private
145 */
1461exports.handleSingleCommandResultReturn = function(override_value_true, override_value_false, callback) {
1470 return function(err, result, connection) {
1480 if(err && typeof callback == 'function') return callback(err, null);
1490 if(!result || !result.documents || result.documents.length == 0)
1500 if(typeof callback == 'function') return callback(toError("command failed to return results"), null)
1510 if(result && result.documents[0].ok == 1) {
1520 if(override_value_true) return callback(null, override_value_true)
1530 if(typeof callback == 'function') return callback(null, result.documents[0]);
154 }
155
156 // Return the error from the document
1570 if(typeof callback == 'function') return callback(toError(result.documents[0]), override_value_false);
158 }
159}
160
161/**
162 * Return correct processor
163 * @ignore
164 * @api private
165 */
1661exports.processor = function() {
167 // Set processor, setImmediate if 0.10 otherwise nextTick
16810 process.maxTickDepth = Infinity;
169 // Only use nextTick
17010 return process.nextTick;
171}
172
173/**
174 * Allow setting the socketTimeoutMS on all connections
175 * to work around issues such as secondaries blocking due to compaction
176 *
177 * @ignore
178 * @api private
179 */
1801exports.setSocketTimeoutProperty = function(self, options) {
1810 Object.defineProperty(self, "socketTimeoutMS", {
182 enumerable: true
1830 , get: function () { return options.socketTimeoutMS; }
184 , set: function (value) {
185 // Set the socket timeoutMS value
1860 options.socketTimeoutMS = value;
187
188 // Get all the connections
1890 var connections = self.allRawConnections();
1900 for(var i = 0; i < connections.length; i++) {
1910 connections[i].socketTimeoutMS = value;
192 }
193 }
194 });
195}
196
1971exports.hasWriteCommands = function(connection) {
1980 return connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasWriteCommands;
199}
200
201
202
203

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/binary.js

18%
121
22
99
LineHitsSource
1/**
2 * Module dependencies.
3 */
41if(typeof window === 'undefined') {
51 var Buffer = require('buffer').Buffer; // TODO just use global Buffer
6}
7
8// Binary default subtype
91var BSON_BINARY_SUBTYPE_DEFAULT = 0;
10
11/**
12 * @ignore
13 * @api private
14 */
151var writeStringToArray = function(data) {
16 // Create a buffer
170 var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(data.length)) : new Array(data.length);
18 // Write the content to the buffer
190 for(var i = 0; i < data.length; i++) {
200 buffer[i] = data.charCodeAt(i);
21 }
22 // Write the string to the buffer
230 return buffer;
24}
25
26/**
27 * Convert Array ot Uint8Array to Binary String
28 *
29 * @ignore
30 * @api private
31 */
321var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) {
330 var result = "";
340 for(var i = startIndex; i < endIndex; i++) {
350 result = result + String.fromCharCode(byteArray[i]);
36 }
370 return result;
38};
39
40/**
41 * A class representation of the BSON Binary type.
42 *
43 * Sub types
44 * - **BSON.BSON_BINARY_SUBTYPE_DEFAULT**, default BSON type.
45 * - **BSON.BSON_BINARY_SUBTYPE_FUNCTION**, BSON function type.
46 * - **BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY**, BSON byte array type.
47 * - **BSON.BSON_BINARY_SUBTYPE_UUID**, BSON uuid type.
48 * - **BSON.BSON_BINARY_SUBTYPE_MD5**, BSON md5 type.
49 * - **BSON.BSON_BINARY_SUBTYPE_USER_DEFINED**, BSON user defined type.
50 *
51 * @class Represents the Binary BSON type.
52 * @param {Buffer} buffer a buffer object containing the binary data.
53 * @param {Number} [subType] the option binary type.
54 * @return {Grid}
55 */
561function Binary(buffer, subType) {
570 if(!(this instanceof Binary)) return new Binary(buffer, subType);
58
590 this._bsontype = 'Binary';
60
610 if(buffer instanceof Number) {
620 this.sub_type = buffer;
630 this.position = 0;
64 } else {
650 this.sub_type = subType == null ? BSON_BINARY_SUBTYPE_DEFAULT : subType;
660 this.position = 0;
67 }
68
690 if(buffer != null && !(buffer instanceof Number)) {
70 // Only accept Buffer, Uint8Array or Arrays
710 if(typeof buffer == 'string') {
72 // Different ways of writing the length of the string for the different types
730 if(typeof Buffer != 'undefined') {
740 this.buffer = new Buffer(buffer);
750 } else if(typeof Uint8Array != 'undefined' || (Object.prototype.toString.call(buffer) == '[object Array]')) {
760 this.buffer = writeStringToArray(buffer);
77 } else {
780 throw new Error("only String, Buffer, Uint8Array or Array accepted");
79 }
80 } else {
810 this.buffer = buffer;
82 }
830 this.position = buffer.length;
84 } else {
850 if(typeof Buffer != 'undefined') {
860 this.buffer = new Buffer(Binary.BUFFER_SIZE);
870 } else if(typeof Uint8Array != 'undefined'){
880 this.buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE));
89 } else {
900 this.buffer = new Array(Binary.BUFFER_SIZE);
91 }
92 // Set position to start of buffer
930 this.position = 0;
94 }
95};
96
97/**
98 * Updates this binary with byte_value.
99 *
100 * @param {Character} byte_value a single byte we wish to write.
101 * @api public
102 */
1031Binary.prototype.put = function put(byte_value) {
104 // If it's a string and a has more than one character throw an error
1050 if(byte_value['length'] != null && typeof byte_value != 'number' && byte_value.length != 1) throw new Error("only accepts single character String, Uint8Array or Array");
1060 if(typeof byte_value != 'number' && byte_value < 0 || byte_value > 255) throw new Error("only accepts number in a valid unsigned byte range 0-255");
107
108 // Decode the byte value once
1090 var decoded_byte = null;
1100 if(typeof byte_value == 'string') {
1110 decoded_byte = byte_value.charCodeAt(0);
1120 } else if(byte_value['length'] != null) {
1130 decoded_byte = byte_value[0];
114 } else {
1150 decoded_byte = byte_value;
116 }
117
1180 if(this.buffer.length > this.position) {
1190 this.buffer[this.position++] = decoded_byte;
120 } else {
1210 if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) {
122 // Create additional overflow buffer
1230 var buffer = new Buffer(Binary.BUFFER_SIZE + this.buffer.length);
124 // Combine the two buffers together
1250 this.buffer.copy(buffer, 0, 0, this.buffer.length);
1260 this.buffer = buffer;
1270 this.buffer[this.position++] = decoded_byte;
128 } else {
1290 var buffer = null;
130 // Create a new buffer (typed or normal array)
1310 if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') {
1320 buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE + this.buffer.length));
133 } else {
1340 buffer = new Array(Binary.BUFFER_SIZE + this.buffer.length);
135 }
136
137 // We need to copy all the content to the new array
1380 for(var i = 0; i < this.buffer.length; i++) {
1390 buffer[i] = this.buffer[i];
140 }
141
142 // Reassign the buffer
1430 this.buffer = buffer;
144 // Write the byte
1450 this.buffer[this.position++] = decoded_byte;
146 }
147 }
148};
149
150/**
151 * Writes a buffer or string to the binary.
152 *
153 * @param {Buffer|String} string a string or buffer to be written to the Binary BSON object.
154 * @param {Number} offset specify the binary of where to write the content.
155 * @api public
156 */
1571Binary.prototype.write = function write(string, offset) {
1580 offset = typeof offset == 'number' ? offset : this.position;
159
160 // If the buffer is to small let's extend the buffer
1610 if(this.buffer.length < offset + string.length) {
1620 var buffer = null;
163 // If we are in node.js
1640 if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) {
1650 buffer = new Buffer(this.buffer.length + string.length);
1660 this.buffer.copy(buffer, 0, 0, this.buffer.length);
1670 } else if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') {
168 // Create a new buffer
1690 buffer = new Uint8Array(new ArrayBuffer(this.buffer.length + string.length))
170 // Copy the content
1710 for(var i = 0; i < this.position; i++) {
1720 buffer[i] = this.buffer[i];
173 }
174 }
175
176 // Assign the new buffer
1770 this.buffer = buffer;
178 }
179
1800 if(typeof Buffer != 'undefined' && Buffer.isBuffer(string) && Buffer.isBuffer(this.buffer)) {
1810 string.copy(this.buffer, offset, 0, string.length);
1820 this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position;
183 // offset = string.length
1840 } else if(typeof Buffer != 'undefined' && typeof string == 'string' && Buffer.isBuffer(this.buffer)) {
1850 this.buffer.write(string, 'binary', offset);
1860 this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position;
187 // offset = string.length;
1880 } else if(Object.prototype.toString.call(string) == '[object Uint8Array]'
189 || Object.prototype.toString.call(string) == '[object Array]' && typeof string != 'string') {
1900 for(var i = 0; i < string.length; i++) {
1910 this.buffer[offset++] = string[i];
192 }
193
1940 this.position = offset > this.position ? offset : this.position;
1950 } else if(typeof string == 'string') {
1960 for(var i = 0; i < string.length; i++) {
1970 this.buffer[offset++] = string.charCodeAt(i);
198 }
199
2000 this.position = offset > this.position ? offset : this.position;
201 }
202};
203
204/**
205 * Reads **length** bytes starting at **position**.
206 *
207 * @param {Number} position read from the given position in the Binary.
208 * @param {Number} length the number of bytes to read.
209 * @return {Buffer}
210 * @api public
211 */
2121Binary.prototype.read = function read(position, length) {
2130 length = length && length > 0
214 ? length
215 : this.position;
216
217 // Let's return the data based on the type we have
2180 if(this.buffer['slice']) {
2190 return this.buffer.slice(position, position + length);
220 } else {
221 // Create a buffer to keep the result
2220 var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(length)) : new Array(length);
2230 for(var i = 0; i < length; i++) {
2240 buffer[i] = this.buffer[position++];
225 }
226 }
227 // Return the buffer
2280 return buffer;
229};
230
231/**
232 * Returns the value of this binary as a string.
233 *
234 * @return {String}
235 * @api public
236 */
2371Binary.prototype.value = function value(asRaw) {
2380 asRaw = asRaw == null ? false : asRaw;
239
240 // If it's a node.js buffer object
2410 if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) {
2420 return asRaw ? this.buffer.slice(0, this.position) : this.buffer.toString('binary', 0, this.position);
243 } else {
2440 if(asRaw) {
245 // we support the slice command use it
2460 if(this.buffer['slice'] != null) {
2470 return this.buffer.slice(0, this.position);
248 } else {
249 // Create a new buffer to copy content to
2500 var newBuffer = Object.prototype.toString.call(this.buffer) == '[object Uint8Array]' ? new Uint8Array(new ArrayBuffer(this.position)) : new Array(this.position);
251 // Copy content
2520 for(var i = 0; i < this.position; i++) {
2530 newBuffer[i] = this.buffer[i];
254 }
255 // Return the buffer
2560 return newBuffer;
257 }
258 } else {
2590 return convertArraytoUtf8BinaryString(this.buffer, 0, this.position);
260 }
261 }
262};
263
264/**
265 * Length.
266 *
267 * @return {Number} the length of the binary.
268 * @api public
269 */
2701Binary.prototype.length = function length() {
2710 return this.position;
272};
273
274/**
275 * @ignore
276 * @api private
277 */
2781Binary.prototype.toJSON = function() {
2790 return this.buffer != null ? this.buffer.toString('base64') : '';
280}
281
282/**
283 * @ignore
284 * @api private
285 */
2861Binary.prototype.toString = function(format) {
2870 return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : '';
288}
289
2901Binary.BUFFER_SIZE = 256;
291
292/**
293 * Default BSON type
294 *
295 * @classconstant SUBTYPE_DEFAULT
296 **/
2971Binary.SUBTYPE_DEFAULT = 0;
298/**
299 * Function BSON type
300 *
301 * @classconstant SUBTYPE_DEFAULT
302 **/
3031Binary.SUBTYPE_FUNCTION = 1;
304/**
305 * Byte Array BSON type
306 *
307 * @classconstant SUBTYPE_DEFAULT
308 **/
3091Binary.SUBTYPE_BYTE_ARRAY = 2;
310/**
311 * OLD UUID BSON type
312 *
313 * @classconstant SUBTYPE_DEFAULT
314 **/
3151Binary.SUBTYPE_UUID_OLD = 3;
316/**
317 * UUID BSON type
318 *
319 * @classconstant SUBTYPE_DEFAULT
320 **/
3211Binary.SUBTYPE_UUID = 4;
322/**
323 * MD5 BSON type
324 *
325 * @classconstant SUBTYPE_DEFAULT
326 **/
3271Binary.SUBTYPE_MD5 = 5;
328/**
329 * User BSON type
330 *
331 * @classconstant SUBTYPE_DEFAULT
332 **/
3331Binary.SUBTYPE_USER_DEFINED = 128;
334
335/**
336 * Expose.
337 */
3381exports.Binary = Binary;
339
340

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js

22%
198
45
153
LineHitsSource
1/**
2 * Binary Parser.
3 * Jonas Raoni Soares Silva
4 * http://jsfromhell.com/classes/binary-parser [v1.0]
5 */
61var chr = String.fromCharCode;
7
81var maxBits = [];
91for (var i = 0; i < 64; i++) {
1064 maxBits[i] = Math.pow(2, i);
11}
12
131function BinaryParser (bigEndian, allowExceptions) {
140 if(!(this instanceof BinaryParser)) return new BinaryParser(bigEndian, allowExceptions);
15
160 this.bigEndian = bigEndian;
170 this.allowExceptions = allowExceptions;
18};
19
201BinaryParser.warn = function warn (msg) {
210 if (this.allowExceptions) {
220 throw new Error(msg);
23 }
24
250 return 1;
26};
27
281BinaryParser.decodeFloat = function decodeFloat (data, precisionBits, exponentBits) {
290 var b = new this.Buffer(this.bigEndian, data);
30
310 b.checkBuffer(precisionBits + exponentBits + 1);
32
330 var bias = maxBits[exponentBits - 1] - 1
34 , signal = b.readBits(precisionBits + exponentBits, 1)
35 , exponent = b.readBits(precisionBits, exponentBits)
36 , significand = 0
37 , divisor = 2
38 , curByte = b.buffer.length + (-precisionBits >> 3) - 1;
39
400 do {
410 for (var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 );
42 } while (precisionBits -= startBit);
43
440 return exponent == ( bias << 1 ) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity : ( 1 + signal * -2 ) * ( exponent || significand ? !exponent ? Math.pow( 2, -bias + 1 ) * significand : Math.pow( 2, exponent - bias ) * ( 1 + significand ) : 0 );
45};
46
471BinaryParser.decodeInt = function decodeInt (data, bits, signed, forceBigEndian) {
480 var b = new this.Buffer(this.bigEndian || forceBigEndian, data)
49 , x = b.readBits(0, bits)
50 , max = maxBits[bits]; //max = Math.pow( 2, bits );
51
520 return signed && x >= max / 2
53 ? x - max
54 : x;
55};
56
571BinaryParser.encodeFloat = function encodeFloat (data, precisionBits, exponentBits) {
580 var bias = maxBits[exponentBits - 1] - 1
59 , minExp = -bias + 1
60 , maxExp = bias
61 , minUnnormExp = minExp - precisionBits
62 , n = parseFloat(data)
63 , status = isNaN(n) || n == -Infinity || n == +Infinity ? n : 0
64 , exp = 0
65 , len = 2 * bias + 1 + precisionBits + 3
66 , bin = new Array(len)
67 , signal = (n = status !== 0 ? 0 : n) < 0
68 , intPart = Math.floor(n = Math.abs(n))
69 , floatPart = n - intPart
70 , lastBit
71 , rounded
72 , result
73 , i
74 , j;
75
760 for (i = len; i; bin[--i] = 0);
77
780 for (i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2));
79
800 for (i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0 ) && --floatPart);
81
820 for (i = -1; ++i < len && !bin[i];);
83
840 if (bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]) {
850 if (!(rounded = bin[lastBit])) {
860 for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]);
87 }
88
890 for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0));
90 }
91
920 for (i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];);
93
940 if ((exp = bias + 1 - i) >= minExp && exp <= maxExp) {
950 ++i;
960 } else if (exp < minExp) {
970 exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow");
980 i = bias + 1 - (exp = minExp - 1);
99 }
100
1010 if (intPart || status !== 0) {
1020 this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status);
1030 exp = maxExp + 1;
1040 i = bias + 2;
105
1060 if (status == -Infinity) {
1070 signal = 1;
1080 } else if (isNaN(status)) {
1090 bin[i] = 1;
110 }
111 }
112
1130 for (n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1);
114
1150 for (n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; i; j = (j + 1) % 8) {
1160 n += (1 << j) * result.charAt(--i);
1170 if (j == 7) {
1180 r[r.length] = String.fromCharCode(n);
1190 n = 0;
120 }
121 }
122
1230 r[r.length] = n
124 ? String.fromCharCode(n)
125 : "";
126
1270 return (this.bigEndian ? r.reverse() : r).join("");
128};
129
1301BinaryParser.encodeInt = function encodeInt (data, bits, signed, forceBigEndian) {
1310 var max = maxBits[bits];
132
1330 if (data >= max || data < -(max / 2)) {
1340 this.warn("encodeInt::overflow");
1350 data = 0;
136 }
137
1380 if (data < 0) {
1390 data += max;
140 }
141
1420 for (var r = []; data; r[r.length] = String.fromCharCode(data % 256), data = Math.floor(data / 256));
143
1440 for (bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0");
145
1460 return ((this.bigEndian || forceBigEndian) ? r.reverse() : r).join("");
147};
148
1491BinaryParser.toSmall = function( data ){ return this.decodeInt( data, 8, true ); };
1501BinaryParser.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); };
1511BinaryParser.toByte = function( data ){ return this.decodeInt( data, 8, false ); };
1521BinaryParser.fromByte = function( data ){ return this.encodeInt( data, 8, false ); };
1531BinaryParser.toShort = function( data ){ return this.decodeInt( data, 16, true ); };
1541BinaryParser.fromShort = function( data ){ return this.encodeInt( data, 16, true ); };
1551BinaryParser.toWord = function( data ){ return this.decodeInt( data, 16, false ); };
1561BinaryParser.fromWord = function( data ){ return this.encodeInt( data, 16, false ); };
1571BinaryParser.toInt = function( data ){ return this.decodeInt( data, 32, true ); };
1581BinaryParser.fromInt = function( data ){ return this.encodeInt( data, 32, true ); };
1591BinaryParser.toLong = function( data ){ return this.decodeInt( data, 64, true ); };
1601BinaryParser.fromLong = function( data ){ return this.encodeInt( data, 64, true ); };
1611BinaryParser.toDWord = function( data ){ return this.decodeInt( data, 32, false ); };
1621BinaryParser.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); };
1631BinaryParser.toQWord = function( data ){ return this.decodeInt( data, 64, true ); };
1641BinaryParser.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); };
1651BinaryParser.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); };
1661BinaryParser.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); };
1671BinaryParser.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); };
1681BinaryParser.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); };
169
170// Factor out the encode so it can be shared by add_header and push_int32
1711BinaryParser.encode_int32 = function encode_int32 (number, asArray) {
1720 var a, b, c, d, unsigned;
1730 unsigned = (number < 0) ? (number + 0x100000000) : number;
1740 a = Math.floor(unsigned / 0xffffff);
1750 unsigned &= 0xffffff;
1760 b = Math.floor(unsigned / 0xffff);
1770 unsigned &= 0xffff;
1780 c = Math.floor(unsigned / 0xff);
1790 unsigned &= 0xff;
1800 d = Math.floor(unsigned);
1810 return asArray ? [chr(a), chr(b), chr(c), chr(d)] : chr(a) + chr(b) + chr(c) + chr(d);
182};
183
1841BinaryParser.encode_int64 = function encode_int64 (number) {
1850 var a, b, c, d, e, f, g, h, unsigned;
1860 unsigned = (number < 0) ? (number + 0x10000000000000000) : number;
1870 a = Math.floor(unsigned / 0xffffffffffffff);
1880 unsigned &= 0xffffffffffffff;
1890 b = Math.floor(unsigned / 0xffffffffffff);
1900 unsigned &= 0xffffffffffff;
1910 c = Math.floor(unsigned / 0xffffffffff);
1920 unsigned &= 0xffffffffff;
1930 d = Math.floor(unsigned / 0xffffffff);
1940 unsigned &= 0xffffffff;
1950 e = Math.floor(unsigned / 0xffffff);
1960 unsigned &= 0xffffff;
1970 f = Math.floor(unsigned / 0xffff);
1980 unsigned &= 0xffff;
1990 g = Math.floor(unsigned / 0xff);
2000 unsigned &= 0xff;
2010 h = Math.floor(unsigned);
2020 return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h);
203};
204
205/**
206 * UTF8 methods
207 */
208
209// Take a raw binary string and return a utf8 string
2101BinaryParser.decode_utf8 = function decode_utf8 (binaryStr) {
2110 var len = binaryStr.length
212 , decoded = ''
213 , i = 0
214 , c = 0
215 , c1 = 0
216 , c2 = 0
217 , c3;
218
2190 while (i < len) {
2200 c = binaryStr.charCodeAt(i);
2210 if (c < 128) {
2220 decoded += String.fromCharCode(c);
2230 i++;
2240 } else if ((c > 191) && (c < 224)) {
2250 c2 = binaryStr.charCodeAt(i+1);
2260 decoded += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
2270 i += 2;
228 } else {
2290 c2 = binaryStr.charCodeAt(i+1);
2300 c3 = binaryStr.charCodeAt(i+2);
2310 decoded += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
2320 i += 3;
233 }
234 }
235
2360 return decoded;
237};
238
239// Encode a cstring
2401BinaryParser.encode_cstring = function encode_cstring (s) {
2410 return unescape(encodeURIComponent(s)) + BinaryParser.fromByte(0);
242};
243
244// Take a utf8 string and return a binary string
2451BinaryParser.encode_utf8 = function encode_utf8 (s) {
2460 var a = ""
247 , c;
248
2490 for (var n = 0, len = s.length; n < len; n++) {
2500 c = s.charCodeAt(n);
251
2520 if (c < 128) {
2530 a += String.fromCharCode(c);
2540 } else if ((c > 127) && (c < 2048)) {
2550 a += String.fromCharCode((c>>6) | 192) ;
2560 a += String.fromCharCode((c&63) | 128);
257 } else {
2580 a += String.fromCharCode((c>>12) | 224);
2590 a += String.fromCharCode(((c>>6) & 63) | 128);
2600 a += String.fromCharCode((c&63) | 128);
261 }
262 }
263
2640 return a;
265};
266
2671BinaryParser.hprint = function hprint (s) {
2680 var number;
269
2700 for (var i = 0, len = s.length; i < len; i++) {
2710 if (s.charCodeAt(i) < 32) {
2720 number = s.charCodeAt(i) <= 15
273 ? "0" + s.charCodeAt(i).toString(16)
274 : s.charCodeAt(i).toString(16);
2750 process.stdout.write(number + " ")
276 } else {
2770 number = s.charCodeAt(i) <= 15
278 ? "0" + s.charCodeAt(i).toString(16)
279 : s.charCodeAt(i).toString(16);
2800 process.stdout.write(number + " ")
281 }
282 }
283
2840 process.stdout.write("\n\n");
285};
286
2871BinaryParser.ilprint = function hprint (s) {
2880 var number;
289
2900 for (var i = 0, len = s.length; i < len; i++) {
2910 if (s.charCodeAt(i) < 32) {
2920 number = s.charCodeAt(i) <= 15
293 ? "0" + s.charCodeAt(i).toString(10)
294 : s.charCodeAt(i).toString(10);
295
2960 require('util').debug(number+' : ');
297 } else {
2980 number = s.charCodeAt(i) <= 15
299 ? "0" + s.charCodeAt(i).toString(10)
300 : s.charCodeAt(i).toString(10);
3010 require('util').debug(number+' : '+ s.charAt(i));
302 }
303 }
304};
305
3061BinaryParser.hlprint = function hprint (s) {
3070 var number;
308
3090 for (var i = 0, len = s.length; i < len; i++) {
3100 if (s.charCodeAt(i) < 32) {
3110 number = s.charCodeAt(i) <= 15
312 ? "0" + s.charCodeAt(i).toString(16)
313 : s.charCodeAt(i).toString(16);
3140 require('util').debug(number+' : ');
315 } else {
3160 number = s.charCodeAt(i) <= 15
317 ? "0" + s.charCodeAt(i).toString(16)
318 : s.charCodeAt(i).toString(16);
3190 require('util').debug(number+' : '+ s.charAt(i));
320 }
321 }
322};
323
324/**
325 * BinaryParser buffer constructor.
326 */
3271function BinaryParserBuffer (bigEndian, buffer) {
3280 this.bigEndian = bigEndian || 0;
3290 this.buffer = [];
3300 this.setBuffer(buffer);
331};
332
3331BinaryParserBuffer.prototype.setBuffer = function setBuffer (data) {
3340 var l, i, b;
335
3360 if (data) {
3370 i = l = data.length;
3380 b = this.buffer = new Array(l);
3390 for (; i; b[l - i] = data.charCodeAt(--i));
3400 this.bigEndian && b.reverse();
341 }
342};
343
3441BinaryParserBuffer.prototype.hasNeededBits = function hasNeededBits (neededBits) {
3450 return this.buffer.length >= -(-neededBits >> 3);
346};
347
3481BinaryParserBuffer.prototype.checkBuffer = function checkBuffer (neededBits) {
3490 if (!this.hasNeededBits(neededBits)) {
3500 throw new Error("checkBuffer::missing bytes");
351 }
352};
353
3541BinaryParserBuffer.prototype.readBits = function readBits (start, length) {
355 //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni)
356
3570 function shl (a, b) {
3580 for (; b--; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1);
3590 return a;
360 }
361
3620 if (start < 0 || length <= 0) {
3630 return 0;
364 }
365
3660 this.checkBuffer(start + length);
367
3680 var offsetLeft
369 , offsetRight = start % 8
370 , curByte = this.buffer.length - ( start >> 3 ) - 1
371 , lastByte = this.buffer.length + ( -( start + length ) >> 3 )
372 , diff = curByte - lastByte
373 , sum = ((this.buffer[ curByte ] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1)) + (diff && (offsetLeft = (start + length) % 8) ? (this.buffer[lastByte++] & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight : 0);
374
3750 for(; diff; sum += shl(this.buffer[lastByte++], (diff-- << 3) - offsetRight));
376
3770 return sum;
378};
379
380/**
381 * Expose.
382 */
3831BinaryParser.Buffer = BinaryParserBuffer;
384
3851exports.BinaryParser = BinaryParser;
386

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/bson.js

10%
670
71
599
LineHitsSource
11var Long = require('./long').Long
2 , Double = require('./double').Double
3 , Timestamp = require('./timestamp').Timestamp
4 , ObjectID = require('./objectid').ObjectID
5 , Symbol = require('./symbol').Symbol
6 , Code = require('./code').Code
7 , MinKey = require('./min_key').MinKey
8 , MaxKey = require('./max_key').MaxKey
9 , DBRef = require('./db_ref').DBRef
10 , Binary = require('./binary').Binary
11 , BinaryParser = require('./binary_parser').BinaryParser
12 , writeIEEE754 = require('./float_parser').writeIEEE754
13 , readIEEE754 = require('./float_parser').readIEEE754
14
15// To ensure that 0.4 of node works correctly
161var isDate = function isDate(d) {
170 return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]';
18}
19
20/**
21 * Create a new BSON instance
22 *
23 * @class Represents the BSON Parser
24 * @return {BSON} instance of BSON Parser.
25 */
261function BSON () {};
27
28/**
29 * @ignore
30 * @api private
31 */
32// BSON MAX VALUES
331BSON.BSON_INT32_MAX = 0x7FFFFFFF;
341BSON.BSON_INT32_MIN = -0x80000000;
35
361BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1;
371BSON.BSON_INT64_MIN = -Math.pow(2, 63);
38
39// JS MAX PRECISE VALUES
401BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double.
411BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double.
42
43// Internal long versions
441var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double.
451var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double.
46
47/**
48 * Number BSON Type
49 *
50 * @classconstant BSON_DATA_NUMBER
51 **/
521BSON.BSON_DATA_NUMBER = 1;
53/**
54 * String BSON Type
55 *
56 * @classconstant BSON_DATA_STRING
57 **/
581BSON.BSON_DATA_STRING = 2;
59/**
60 * Object BSON Type
61 *
62 * @classconstant BSON_DATA_OBJECT
63 **/
641BSON.BSON_DATA_OBJECT = 3;
65/**
66 * Array BSON Type
67 *
68 * @classconstant BSON_DATA_ARRAY
69 **/
701BSON.BSON_DATA_ARRAY = 4;
71/**
72 * Binary BSON Type
73 *
74 * @classconstant BSON_DATA_BINARY
75 **/
761BSON.BSON_DATA_BINARY = 5;
77/**
78 * ObjectID BSON Type
79 *
80 * @classconstant BSON_DATA_OID
81 **/
821BSON.BSON_DATA_OID = 7;
83/**
84 * Boolean BSON Type
85 *
86 * @classconstant BSON_DATA_BOOLEAN
87 **/
881BSON.BSON_DATA_BOOLEAN = 8;
89/**
90 * Date BSON Type
91 *
92 * @classconstant BSON_DATA_DATE
93 **/
941BSON.BSON_DATA_DATE = 9;
95/**
96 * null BSON Type
97 *
98 * @classconstant BSON_DATA_NULL
99 **/
1001BSON.BSON_DATA_NULL = 10;
101/**
102 * RegExp BSON Type
103 *
104 * @classconstant BSON_DATA_REGEXP
105 **/
1061BSON.BSON_DATA_REGEXP = 11;
107/**
108 * Code BSON Type
109 *
110 * @classconstant BSON_DATA_CODE
111 **/
1121BSON.BSON_DATA_CODE = 13;
113/**
114 * Symbol BSON Type
115 *
116 * @classconstant BSON_DATA_SYMBOL
117 **/
1181BSON.BSON_DATA_SYMBOL = 14;
119/**
120 * Code with Scope BSON Type
121 *
122 * @classconstant BSON_DATA_CODE_W_SCOPE
123 **/
1241BSON.BSON_DATA_CODE_W_SCOPE = 15;
125/**
126 * 32 bit Integer BSON Type
127 *
128 * @classconstant BSON_DATA_INT
129 **/
1301BSON.BSON_DATA_INT = 16;
131/**
132 * Timestamp BSON Type
133 *
134 * @classconstant BSON_DATA_TIMESTAMP
135 **/
1361BSON.BSON_DATA_TIMESTAMP = 17;
137/**
138 * Long BSON Type
139 *
140 * @classconstant BSON_DATA_LONG
141 **/
1421BSON.BSON_DATA_LONG = 18;
143/**
144 * MinKey BSON Type
145 *
146 * @classconstant BSON_DATA_MIN_KEY
147 **/
1481BSON.BSON_DATA_MIN_KEY = 0xff;
149/**
150 * MaxKey BSON Type
151 *
152 * @classconstant BSON_DATA_MAX_KEY
153 **/
1541BSON.BSON_DATA_MAX_KEY = 0x7f;
155
156/**
157 * Binary Default Type
158 *
159 * @classconstant BSON_BINARY_SUBTYPE_DEFAULT
160 **/
1611BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0;
162/**
163 * Binary Function Type
164 *
165 * @classconstant BSON_BINARY_SUBTYPE_FUNCTION
166 **/
1671BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1;
168/**
169 * Binary Byte Array Type
170 *
171 * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY
172 **/
1731BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2;
174/**
175 * Binary UUID Type
176 *
177 * @classconstant BSON_BINARY_SUBTYPE_UUID
178 **/
1791BSON.BSON_BINARY_SUBTYPE_UUID = 3;
180/**
181 * Binary MD5 Type
182 *
183 * @classconstant BSON_BINARY_SUBTYPE_MD5
184 **/
1851BSON.BSON_BINARY_SUBTYPE_MD5 = 4;
186/**
187 * Binary User Defined Type
188 *
189 * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED
190 **/
1911BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128;
192
193/**
194 * Calculate the bson size for a passed in Javascript object.
195 *
196 * @param {Object} object the Javascript object to calculate the BSON byte size for.
197 * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**.
198 * @return {Number} returns the number of bytes the BSON object will take up.
199 * @api public
200 */
2011BSON.calculateObjectSize = function calculateObjectSize(object, serializeFunctions) {
2020 var totalLength = (4 + 1);
203
2040 if(Array.isArray(object)) {
2050 for(var i = 0; i < object.length; i++) {
2060 totalLength += calculateElement(i.toString(), object[i], serializeFunctions)
207 }
208 } else {
209 // If we have toBSON defined, override the current object
2100 if(object.toBSON) {
2110 object = object.toBSON();
212 }
213
214 // Calculate size
2150 for(var key in object) {
2160 totalLength += calculateElement(key, object[key], serializeFunctions)
217 }
218 }
219
2200 return totalLength;
221}
222
223/**
224 * @ignore
225 * @api private
226 */
2271function calculateElement(name, value, serializeFunctions) {
2280 var isBuffer = typeof Buffer !== 'undefined';
229
2300 switch(typeof value) {
231 case 'string':
2320 return 1 + (!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1 + 4 + (!isBuffer ? numberOfBytes(value) : Buffer.byteLength(value, 'utf8')) + 1;
233 case 'number':
2340 if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
2350 if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit
2360 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (4 + 1);
237 } else {
2380 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1);
239 }
240 } else { // 64 bit
2410 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1);
242 }
243 case 'undefined':
2440 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1);
245 case 'boolean':
2460 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 1);
247 case 'object':
2480 if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') {
2490 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1);
2500 } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') {
2510 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (12 + 1);
2520 } else if(value instanceof Date || isDate(value)) {
2530 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1);
2540 } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
2550 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 4 + 1) + value.length;
2560 } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp
257 || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') {
2580 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1);
2590 } else if(value instanceof Code || value['_bsontype'] == 'Code') {
260 // Calculate size depending on the availability of a scope
2610 if(value.scope != null && Object.keys(value.scope).length > 0) {
2620 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions);
263 } else {
2640 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1;
265 }
2660 } else if(value instanceof Binary || value['_bsontype'] == 'Binary') {
267 // Check what kind of subtype we have
2680 if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) {
2690 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1 + 4);
270 } else {
2710 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1);
272 }
2730 } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') {
2740 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + ((!isBuffer ? numberOfBytes(value.value) : Buffer.byteLength(value.value, 'utf8')) + 4 + 1 + 1);
2750 } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') {
276 // Set up correct object for serialization
2770 var ordered_values = {
278 '$ref': value.namespace
279 , '$id' : value.oid
280 };
281
282 // Add db reference if it exists
2830 if(null != value.db) {
2840 ordered_values['$db'] = value.db;
285 }
286
2870 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + BSON.calculateObjectSize(ordered_values, serializeFunctions);
2880 } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') {
2890 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1
290 + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1
291 } else {
2920 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + BSON.calculateObjectSize(value, serializeFunctions) + 1;
293 }
294 case 'function':
295 // WTF for 0.4.X where typeof /someregexp/ === 'function'
2960 if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') {
2970 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1
298 + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1
299 } else {
3000 if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) {
3010 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions);
3020 } else if(serializeFunctions) {
3030 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1;
304 }
305 }
306 }
307
3080 return 0;
309}
310
311/**
312 * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization.
313 *
314 * @param {Object} object the Javascript object to serialize.
315 * @param {Boolean} checkKeys the serializer will check if keys are valid.
316 * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object.
317 * @param {Number} index the index in the buffer where we wish to start serializing into.
318 * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**.
319 * @return {Number} returns the new write index in the Buffer.
320 * @api public
321 */
3221BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, checkKeys, buffer, index, serializeFunctions) {
323 // Default setting false
3240 serializeFunctions = serializeFunctions == null ? false : serializeFunctions;
325 // Write end information (length of the object)
3260 var size = buffer.length;
327 // Write the size of the object
3280 buffer[index++] = size & 0xff;
3290 buffer[index++] = (size >> 8) & 0xff;
3300 buffer[index++] = (size >> 16) & 0xff;
3310 buffer[index++] = (size >> 24) & 0xff;
3320 return serializeObject(object, checkKeys, buffer, index, serializeFunctions) - 1;
333}
334
335/**
336 * @ignore
337 * @api private
338 */
3391var serializeObject = function(object, checkKeys, buffer, index, serializeFunctions) {
340 // Process the object
3410 if(Array.isArray(object)) {
3420 for(var i = 0; i < object.length; i++) {
3430 index = packElement(i.toString(), object[i], checkKeys, buffer, index, serializeFunctions);
344 }
345 } else {
346 // If we have toBSON defined, override the current object
3470 if(object.toBSON) {
3480 object = object.toBSON();
349 }
350
351 // Serialize the object
3520 for(var key in object) {
353 // Check the key and throw error if it's illegal
3540 if (key != '$db' && key != '$ref' && key != '$id') {
355 // dollars and dots ok
3560 BSON.checkKey(key, !checkKeys);
357 }
358
359 // Pack the element
3600 index = packElement(key, object[key], checkKeys, buffer, index, serializeFunctions);
361 }
362 }
363
364 // Write zero
3650 buffer[index++] = 0;
3660 return index;
367}
368
3691var stringToBytes = function(str) {
3700 var ch, st, re = [];
3710 for (var i = 0; i < str.length; i++ ) {
3720 ch = str.charCodeAt(i); // get char
3730 st = []; // set up "stack"
3740 do {
3750 st.push( ch & 0xFF ); // push byte to stack
3760 ch = ch >> 8; // shift value down by 1 byte
377 }
378 while ( ch );
379 // add stack contents to result
380 // done because chars have "wrong" endianness
3810 re = re.concat( st.reverse() );
382 }
383 // return an array of bytes
3840 return re;
385}
386
3871var numberOfBytes = function(str) {
3880 var ch, st, re = 0;
3890 for (var i = 0; i < str.length; i++ ) {
3900 ch = str.charCodeAt(i); // get char
3910 st = []; // set up "stack"
3920 do {
3930 st.push( ch & 0xFF ); // push byte to stack
3940 ch = ch >> 8; // shift value down by 1 byte
395 }
396 while ( ch );
397 // add stack contents to result
398 // done because chars have "wrong" endianness
3990 re = re + st.length;
400 }
401 // return an array of bytes
4020 return re;
403}
404
405/**
406 * @ignore
407 * @api private
408 */
4091var writeToTypedArray = function(buffer, string, index) {
4100 var bytes = stringToBytes(string);
4110 for(var i = 0; i < bytes.length; i++) {
4120 buffer[index + i] = bytes[i];
413 }
4140 return bytes.length;
415}
416
417/**
418 * @ignore
419 * @api private
420 */
4211var supportsBuffer = typeof Buffer != 'undefined';
422
423/**
424 * @ignore
425 * @api private
426 */
4271var packElement = function(name, value, checkKeys, buffer, index, serializeFunctions) {
4280 var startIndex = index;
429
4300 switch(typeof value) {
431 case 'string':
432 // Encode String type
4330 buffer[index++] = BSON.BSON_DATA_STRING;
434 // Number of written bytes
4350 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
436 // Encode the name
4370 index = index + numberOfWrittenBytes + 1;
4380 buffer[index - 1] = 0;
439
440 // Calculate size
4410 var size = supportsBuffer ? Buffer.byteLength(value) + 1 : numberOfBytes(value) + 1;
442 // Write the size of the string to buffer
4430 buffer[index + 3] = (size >> 24) & 0xff;
4440 buffer[index + 2] = (size >> 16) & 0xff;
4450 buffer[index + 1] = (size >> 8) & 0xff;
4460 buffer[index] = size & 0xff;
447 // Ajust the index
4480 index = index + 4;
449 // Write the string
4500 supportsBuffer ? buffer.write(value, index, 'utf8') : writeToTypedArray(buffer, value, index);
451 // Update index
4520 index = index + size - 1;
453 // Write zero
4540 buffer[index++] = 0;
455 // Return index
4560 return index;
457 case 'number':
458 // We have an integer value
4590 if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
460 // If the value fits in 32 bits encode as int, if it fits in a double
461 // encode it as a double, otherwise long
4620 if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) {
463 // Set int type 32 bits or less
4640 buffer[index++] = BSON.BSON_DATA_INT;
465 // Number of written bytes
4660 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
467 // Encode the name
4680 index = index + numberOfWrittenBytes + 1;
4690 buffer[index - 1] = 0;
470 // Write the int value
4710 buffer[index++] = value & 0xff;
4720 buffer[index++] = (value >> 8) & 0xff;
4730 buffer[index++] = (value >> 16) & 0xff;
4740 buffer[index++] = (value >> 24) & 0xff;
4750 } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
476 // Encode as double
4770 buffer[index++] = BSON.BSON_DATA_NUMBER;
478 // Number of written bytes
4790 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
480 // Encode the name
4810 index = index + numberOfWrittenBytes + 1;
4820 buffer[index - 1] = 0;
483 // Write float
4840 writeIEEE754(buffer, value, index, 'little', 52, 8);
485 // Ajust index
4860 index = index + 8;
487 } else {
488 // Set long type
4890 buffer[index++] = BSON.BSON_DATA_LONG;
490 // Number of written bytes
4910 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
492 // Encode the name
4930 index = index + numberOfWrittenBytes + 1;
4940 buffer[index - 1] = 0;
4950 var longVal = Long.fromNumber(value);
4960 var lowBits = longVal.getLowBits();
4970 var highBits = longVal.getHighBits();
498 // Encode low bits
4990 buffer[index++] = lowBits & 0xff;
5000 buffer[index++] = (lowBits >> 8) & 0xff;
5010 buffer[index++] = (lowBits >> 16) & 0xff;
5020 buffer[index++] = (lowBits >> 24) & 0xff;
503 // Encode high bits
5040 buffer[index++] = highBits & 0xff;
5050 buffer[index++] = (highBits >> 8) & 0xff;
5060 buffer[index++] = (highBits >> 16) & 0xff;
5070 buffer[index++] = (highBits >> 24) & 0xff;
508 }
509 } else {
510 // Encode as double
5110 buffer[index++] = BSON.BSON_DATA_NUMBER;
512 // Number of written bytes
5130 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
514 // Encode the name
5150 index = index + numberOfWrittenBytes + 1;
5160 buffer[index - 1] = 0;
517 // Write float
5180 writeIEEE754(buffer, value, index, 'little', 52, 8);
519 // Ajust index
5200 index = index + 8;
521 }
522
5230 return index;
524 case 'undefined':
525 // Set long type
5260 buffer[index++] = BSON.BSON_DATA_NULL;
527 // Number of written bytes
5280 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
529 // Encode the name
5300 index = index + numberOfWrittenBytes + 1;
5310 buffer[index - 1] = 0;
5320 return index;
533 case 'boolean':
534 // Write the type
5350 buffer[index++] = BSON.BSON_DATA_BOOLEAN;
536 // Number of written bytes
5370 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
538 // Encode the name
5390 index = index + numberOfWrittenBytes + 1;
5400 buffer[index - 1] = 0;
541 // Encode the boolean value
5420 buffer[index++] = value ? 1 : 0;
5430 return index;
544 case 'object':
5450 if(value === null || value instanceof MinKey || value instanceof MaxKey
546 || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') {
547 // Write the type of either min or max key
5480 if(value === null) {
5490 buffer[index++] = BSON.BSON_DATA_NULL;
5500 } else if(value instanceof MinKey) {
5510 buffer[index++] = BSON.BSON_DATA_MIN_KEY;
552 } else {
5530 buffer[index++] = BSON.BSON_DATA_MAX_KEY;
554 }
555
556 // Number of written bytes
5570 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
558 // Encode the name
5590 index = index + numberOfWrittenBytes + 1;
5600 buffer[index - 1] = 0;
5610 return index;
5620 } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') {
563 // Write the type
5640 buffer[index++] = BSON.BSON_DATA_OID;
565 // Number of written bytes
5660 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
567 // Encode the name
5680 index = index + numberOfWrittenBytes + 1;
5690 buffer[index - 1] = 0;
570
571 // Write objectid
5720 supportsBuffer ? buffer.write(value.id, index, 'binary') : writeToTypedArray(buffer, value.id, index);
573 // Ajust index
5740 index = index + 12;
5750 return index;
5760 } else if(value instanceof Date || isDate(value)) {
577 // Write the type
5780 buffer[index++] = BSON.BSON_DATA_DATE;
579 // Number of written bytes
5800 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
581 // Encode the name
5820 index = index + numberOfWrittenBytes + 1;
5830 buffer[index - 1] = 0;
584
585 // Write the date
5860 var dateInMilis = Long.fromNumber(value.getTime());
5870 var lowBits = dateInMilis.getLowBits();
5880 var highBits = dateInMilis.getHighBits();
589 // Encode low bits
5900 buffer[index++] = lowBits & 0xff;
5910 buffer[index++] = (lowBits >> 8) & 0xff;
5920 buffer[index++] = (lowBits >> 16) & 0xff;
5930 buffer[index++] = (lowBits >> 24) & 0xff;
594 // Encode high bits
5950 buffer[index++] = highBits & 0xff;
5960 buffer[index++] = (highBits >> 8) & 0xff;
5970 buffer[index++] = (highBits >> 16) & 0xff;
5980 buffer[index++] = (highBits >> 24) & 0xff;
5990 return index;
6000 } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
601 // Write the type
6020 buffer[index++] = BSON.BSON_DATA_BINARY;
603 // Number of written bytes
6040 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
605 // Encode the name
6060 index = index + numberOfWrittenBytes + 1;
6070 buffer[index - 1] = 0;
608 // Get size of the buffer (current write point)
6090 var size = value.length;
610 // Write the size of the string to buffer
6110 buffer[index++] = size & 0xff;
6120 buffer[index++] = (size >> 8) & 0xff;
6130 buffer[index++] = (size >> 16) & 0xff;
6140 buffer[index++] = (size >> 24) & 0xff;
615 // Write the default subtype
6160 buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT;
617 // Copy the content form the binary field to the buffer
6180 value.copy(buffer, index, 0, size);
619 // Adjust the index
6200 index = index + size;
6210 return index;
6220 } else if(value instanceof Long || value instanceof Timestamp || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Timestamp') {
623 // Write the type
6240 buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP;
625 // Number of written bytes
6260 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
627 // Encode the name
6280 index = index + numberOfWrittenBytes + 1;
6290 buffer[index - 1] = 0;
630 // Write the date
6310 var lowBits = value.getLowBits();
6320 var highBits = value.getHighBits();
633 // Encode low bits
6340 buffer[index++] = lowBits & 0xff;
6350 buffer[index++] = (lowBits >> 8) & 0xff;
6360 buffer[index++] = (lowBits >> 16) & 0xff;
6370 buffer[index++] = (lowBits >> 24) & 0xff;
638 // Encode high bits
6390 buffer[index++] = highBits & 0xff;
6400 buffer[index++] = (highBits >> 8) & 0xff;
6410 buffer[index++] = (highBits >> 16) & 0xff;
6420 buffer[index++] = (highBits >> 24) & 0xff;
6430 return index;
6440 } else if(value instanceof Double || value['_bsontype'] == 'Double') {
645 // Encode as double
6460 buffer[index++] = BSON.BSON_DATA_NUMBER;
647 // Number of written bytes
6480 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
649 // Encode the name
6500 index = index + numberOfWrittenBytes + 1;
6510 buffer[index - 1] = 0;
652 // Write float
6530 writeIEEE754(buffer, value, index, 'little', 52, 8);
654 // Ajust index
6550 index = index + 8;
6560 return index;
6570 } else if(value instanceof Code || value['_bsontype'] == 'Code') {
6580 if(value.scope != null && Object.keys(value.scope).length > 0) {
659 // Write the type
6600 buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE;
661 // Number of written bytes
6620 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
663 // Encode the name
6640 index = index + numberOfWrittenBytes + 1;
6650 buffer[index - 1] = 0;
666 // Calculate the scope size
6670 var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions);
668 // Function string
6690 var functionString = value.code.toString();
670 // Function Size
6710 var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1;
672
673 // Calculate full size of the object
6740 var totalSize = 4 + codeSize + scopeSize + 4;
675
676 // Write the total size of the object
6770 buffer[index++] = totalSize & 0xff;
6780 buffer[index++] = (totalSize >> 8) & 0xff;
6790 buffer[index++] = (totalSize >> 16) & 0xff;
6800 buffer[index++] = (totalSize >> 24) & 0xff;
681
682 // Write the size of the string to buffer
6830 buffer[index++] = codeSize & 0xff;
6840 buffer[index++] = (codeSize >> 8) & 0xff;
6850 buffer[index++] = (codeSize >> 16) & 0xff;
6860 buffer[index++] = (codeSize >> 24) & 0xff;
687
688 // Write the string
6890 supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index);
690 // Update index
6910 index = index + codeSize - 1;
692 // Write zero
6930 buffer[index++] = 0;
694 // Serialize the scope object
6950 var scopeObjectBuffer = supportsBuffer ? new Buffer(scopeSize) : new Uint8Array(new ArrayBuffer(scopeSize));
696 // Execute the serialization into a seperate buffer
6970 serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions);
698
699 // Adjusted scope Size (removing the header)
7000 var scopeDocSize = scopeSize;
701 // Write scope object size
7020 buffer[index++] = scopeDocSize & 0xff;
7030 buffer[index++] = (scopeDocSize >> 8) & 0xff;
7040 buffer[index++] = (scopeDocSize >> 16) & 0xff;
7050 buffer[index++] = (scopeDocSize >> 24) & 0xff;
706
707 // Write the scopeObject into the buffer
7080 supportsBuffer ? scopeObjectBuffer.copy(buffer, index, 0, scopeSize) : buffer.set(scopeObjectBuffer, index);
709 // Adjust index, removing the empty size of the doc (5 bytes 0000000005)
7100 index = index + scopeDocSize - 5;
711 // Write trailing zero
7120 buffer[index++] = 0;
7130 return index
714 } else {
7150 buffer[index++] = BSON.BSON_DATA_CODE;
716 // Number of written bytes
7170 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
718 // Encode the name
7190 index = index + numberOfWrittenBytes + 1;
7200 buffer[index - 1] = 0;
721 // Function string
7220 var functionString = value.code.toString();
723 // Function Size
7240 var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1;
725 // Write the size of the string to buffer
7260 buffer[index++] = size & 0xff;
7270 buffer[index++] = (size >> 8) & 0xff;
7280 buffer[index++] = (size >> 16) & 0xff;
7290 buffer[index++] = (size >> 24) & 0xff;
730 // Write the string
7310 supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index);
732 // Update index
7330 index = index + size - 1;
734 // Write zero
7350 buffer[index++] = 0;
7360 return index;
737 }
7380 } else if(value instanceof Binary || value['_bsontype'] == 'Binary') {
739 // Write the type
7400 buffer[index++] = BSON.BSON_DATA_BINARY;
741 // Number of written bytes
7420 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
743 // Encode the name
7440 index = index + numberOfWrittenBytes + 1;
7450 buffer[index - 1] = 0;
746 // Extract the buffer
7470 var data = value.value(true);
748 // Calculate size
7490 var size = value.position;
750 // Write the size of the string to buffer
7510 buffer[index++] = size & 0xff;
7520 buffer[index++] = (size >> 8) & 0xff;
7530 buffer[index++] = (size >> 16) & 0xff;
7540 buffer[index++] = (size >> 24) & 0xff;
755 // Write the subtype to the buffer
7560 buffer[index++] = value.sub_type;
757
758 // If we have binary type 2 the 4 first bytes are the size
7590 if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) {
7600 buffer[index++] = size & 0xff;
7610 buffer[index++] = (size >> 8) & 0xff;
7620 buffer[index++] = (size >> 16) & 0xff;
7630 buffer[index++] = (size >> 24) & 0xff;
764 }
765
766 // Write the data to the object
7670 supportsBuffer ? data.copy(buffer, index, 0, value.position) : buffer.set(data, index);
768 // Ajust index
7690 index = index + value.position;
7700 return index;
7710 } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') {
772 // Write the type
7730 buffer[index++] = BSON.BSON_DATA_SYMBOL;
774 // Number of written bytes
7750 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
776 // Encode the name
7770 index = index + numberOfWrittenBytes + 1;
7780 buffer[index - 1] = 0;
779 // Calculate size
7800 var size = supportsBuffer ? Buffer.byteLength(value.value) + 1 : numberOfBytes(value.value) + 1;
781 // Write the size of the string to buffer
7820 buffer[index++] = size & 0xff;
7830 buffer[index++] = (size >> 8) & 0xff;
7840 buffer[index++] = (size >> 16) & 0xff;
7850 buffer[index++] = (size >> 24) & 0xff;
786 // Write the string
7870 buffer.write(value.value, index, 'utf8');
788 // Update index
7890 index = index + size - 1;
790 // Write zero
7910 buffer[index++] = 0x00;
7920 return index;
7930 } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') {
794 // Write the type
7950 buffer[index++] = BSON.BSON_DATA_OBJECT;
796 // Number of written bytes
7970 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
798 // Encode the name
7990 index = index + numberOfWrittenBytes + 1;
8000 buffer[index - 1] = 0;
801 // Set up correct object for serialization
8020 var ordered_values = {
803 '$ref': value.namespace
804 , '$id' : value.oid
805 };
806
807 // Add db reference if it exists
8080 if(null != value.db) {
8090 ordered_values['$db'] = value.db;
810 }
811
812 // Message size
8130 var size = BSON.calculateObjectSize(ordered_values, serializeFunctions);
814 // Serialize the object
8150 var endIndex = BSON.serializeWithBufferAndIndex(ordered_values, checkKeys, buffer, index, serializeFunctions);
816 // Write the size of the string to buffer
8170 buffer[index++] = size & 0xff;
8180 buffer[index++] = (size >> 8) & 0xff;
8190 buffer[index++] = (size >> 16) & 0xff;
8200 buffer[index++] = (size >> 24) & 0xff;
821 // Write zero for object
8220 buffer[endIndex++] = 0x00;
823 // Return the end index
8240 return endIndex;
8250 } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') {
826 // Write the type
8270 buffer[index++] = BSON.BSON_DATA_REGEXP;
828 // Number of written bytes
8290 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
830 // Encode the name
8310 index = index + numberOfWrittenBytes + 1;
8320 buffer[index - 1] = 0;
833
834 // Write the regular expression string
8350 supportsBuffer ? buffer.write(value.source, index, 'utf8') : writeToTypedArray(buffer, value.source, index);
836 // Adjust the index
8370 index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source));
838 // Write zero
8390 buffer[index++] = 0x00;
840 // Write the parameters
8410 if(value.global) buffer[index++] = 0x73; // s
8420 if(value.ignoreCase) buffer[index++] = 0x69; // i
8430 if(value.multiline) buffer[index++] = 0x6d; // m
844 // Add ending zero
8450 buffer[index++] = 0x00;
8460 return index;
847 } else {
848 // Write the type
8490 buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT;
850 // Number of written bytes
8510 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
852 // Adjust the index
8530 index = index + numberOfWrittenBytes + 1;
8540 buffer[index - 1] = 0;
8550 var endIndex = serializeObject(value, checkKeys, buffer, index + 4, serializeFunctions);
856 // Write size
8570 var size = endIndex - index;
858 // Write the size of the string to buffer
8590 buffer[index++] = size & 0xff;
8600 buffer[index++] = (size >> 8) & 0xff;
8610 buffer[index++] = (size >> 16) & 0xff;
8620 buffer[index++] = (size >> 24) & 0xff;
8630 return endIndex;
864 }
865 case 'function':
866 // WTF for 0.4.X where typeof /someregexp/ === 'function'
8670 if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') {
868 // Write the type
8690 buffer[index++] = BSON.BSON_DATA_REGEXP;
870 // Number of written bytes
8710 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
872 // Encode the name
8730 index = index + numberOfWrittenBytes + 1;
8740 buffer[index - 1] = 0;
875
876 // Write the regular expression string
8770 buffer.write(value.source, index, 'utf8');
878 // Adjust the index
8790 index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source));
880 // Write zero
8810 buffer[index++] = 0x00;
882 // Write the parameters
8830 if(value.global) buffer[index++] = 0x73; // s
8840 if(value.ignoreCase) buffer[index++] = 0x69; // i
8850 if(value.multiline) buffer[index++] = 0x6d; // m
886 // Add ending zero
8870 buffer[index++] = 0x00;
8880 return index;
889 } else {
8900 if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) {
891 // Write the type
8920 buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE;
893 // Number of written bytes
8940 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
895 // Encode the name
8960 index = index + numberOfWrittenBytes + 1;
8970 buffer[index - 1] = 0;
898 // Calculate the scope size
8990 var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions);
900 // Function string
9010 var functionString = value.toString();
902 // Function Size
9030 var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1;
904
905 // Calculate full size of the object
9060 var totalSize = 4 + codeSize + scopeSize;
907
908 // Write the total size of the object
9090 buffer[index++] = totalSize & 0xff;
9100 buffer[index++] = (totalSize >> 8) & 0xff;
9110 buffer[index++] = (totalSize >> 16) & 0xff;
9120 buffer[index++] = (totalSize >> 24) & 0xff;
913
914 // Write the size of the string to buffer
9150 buffer[index++] = codeSize & 0xff;
9160 buffer[index++] = (codeSize >> 8) & 0xff;
9170 buffer[index++] = (codeSize >> 16) & 0xff;
9180 buffer[index++] = (codeSize >> 24) & 0xff;
919
920 // Write the string
9210 supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index);
922 // Update index
9230 index = index + codeSize - 1;
924 // Write zero
9250 buffer[index++] = 0;
926 // Serialize the scope object
9270 var scopeObjectBuffer = new Buffer(scopeSize);
928 // Execute the serialization into a seperate buffer
9290 serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions);
930
931 // Adjusted scope Size (removing the header)
9320 var scopeDocSize = scopeSize - 4;
933 // Write scope object size
9340 buffer[index++] = scopeDocSize & 0xff;
9350 buffer[index++] = (scopeDocSize >> 8) & 0xff;
9360 buffer[index++] = (scopeDocSize >> 16) & 0xff;
9370 buffer[index++] = (scopeDocSize >> 24) & 0xff;
938
939 // Write the scopeObject into the buffer
9400 scopeObjectBuffer.copy(buffer, index, 0, scopeSize);
941
942 // Adjust index, removing the empty size of the doc (5 bytes 0000000005)
9430 index = index + scopeDocSize - 5;
944 // Write trailing zero
9450 buffer[index++] = 0;
9460 return index
9470 } else if(serializeFunctions) {
9480 buffer[index++] = BSON.BSON_DATA_CODE;
949 // Number of written bytes
9500 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
951 // Encode the name
9520 index = index + numberOfWrittenBytes + 1;
9530 buffer[index - 1] = 0;
954 // Function string
9550 var functionString = value.toString();
956 // Function Size
9570 var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1;
958 // Write the size of the string to buffer
9590 buffer[index++] = size & 0xff;
9600 buffer[index++] = (size >> 8) & 0xff;
9610 buffer[index++] = (size >> 16) & 0xff;
9620 buffer[index++] = (size >> 24) & 0xff;
963 // Write the string
9640 supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index);
965 // Update index
9660 index = index + size - 1;
967 // Write zero
9680 buffer[index++] = 0;
9690 return index;
970 }
971 }
972 }
973
974 // If no value to serialize
9750 return index;
976}
977
978/**
979 * Serialize a Javascript object.
980 *
981 * @param {Object} object the Javascript object to serialize.
982 * @param {Boolean} checkKeys the serializer will check if keys are valid.
983 * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**.
984 * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**.
985 * @return {Buffer} returns the Buffer object containing the serialized object.
986 * @api public
987 */
9881BSON.serialize = function(object, checkKeys, asBuffer, serializeFunctions) {
989 // Throw error if we are trying serialize an illegal type
9900 if(object == null || typeof object != 'object' || Array.isArray(object))
9910 throw new Error("Only javascript objects supported");
992
993 // Emoty target buffer
9940 var buffer = null;
995 // Calculate the size of the object
9960 var size = BSON.calculateObjectSize(object, serializeFunctions);
997 // Fetch the best available type for storing the binary data
9980 if(buffer = typeof Buffer != 'undefined') {
9990 buffer = new Buffer(size);
10000 asBuffer = true;
10010 } else if(typeof Uint8Array != 'undefined') {
10020 buffer = new Uint8Array(new ArrayBuffer(size));
1003 } else {
10040 buffer = new Array(size);
1005 }
1006
1007 // If asBuffer is false use typed arrays
10080 BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, 0, serializeFunctions);
10090 return buffer;
1010}
1011
1012/**
1013 * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5
1014 *
1015 * @ignore
1016 * @api private
1017 */
10181var functionCache = BSON.functionCache = {};
1019
1020/**
1021 * Crc state variables shared by function
1022 *
1023 * @ignore
1024 * @api private
1025 */
10261var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D];
1027
1028/**
1029 * CRC32 hash method, Fast and enough versitility for our usage
1030 *
1031 * @ignore
1032 * @api private
1033 */
10341var crc32 = function(string, start, end) {
10350 var crc = 0
10360 var x = 0;
10370 var y = 0;
10380 crc = crc ^ (-1);
1039
10400 for(var i = start, iTop = end; i < iTop;i++) {
10410 y = (crc ^ string[i]) & 0xFF;
10420 x = table[y];
10430 crc = (crc >>> 8) ^ x;
1044 }
1045
10460 return crc ^ (-1);
1047}
1048
1049/**
1050 * Deserialize stream data as BSON documents.
1051 *
1052 * Options
1053 * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized.
1054 * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse.
1055 * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function.
1056 * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits
1057 *
1058 * @param {Buffer} data the buffer containing the serialized set of BSON documents.
1059 * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start.
1060 * @param {Number} numberOfDocuments number of documents to deserialize.
1061 * @param {Array} documents an array where to store the deserialized documents.
1062 * @param {Number} docStartIndex the index in the documents array from where to start inserting documents.
1063 * @param {Object} [options] additional options used for the deserialization.
1064 * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents.
1065 * @api public
1066 */
10671BSON.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) {
1068 // if(numberOfDocuments !== documents.length) throw new Error("Number of expected results back is less than the number of documents");
10690 options = options != null ? options : {};
10700 var index = startIndex;
1071 // Loop over all documents
10720 for(var i = 0; i < numberOfDocuments; i++) {
1073 // Find size of the document
10740 var size = data[index] | data[index + 1] << 8 | data[index + 2] << 16 | data[index + 3] << 24;
1075 // Update options with index
10760 options['index'] = index;
1077 // Parse the document at this point
10780 documents[docStartIndex + i] = BSON.deserialize(data, options);
1079 // Adjust index by the document size
10800 index = index + size;
1081 }
1082
1083 // Return object containing end index of parsing and list of documents
10840 return index;
1085}
1086
1087/**
1088 * Ensure eval is isolated.
1089 *
1090 * @ignore
1091 * @api private
1092 */
10931var isolateEvalWithHash = function(functionCache, hash, functionString, object) {
1094 // Contains the value we are going to set
10950 var value = null;
1096
1097 // Check for cache hit, eval if missing and return cached function
10980 if(functionCache[hash] == null) {
10990 eval("value = " + functionString);
11000 functionCache[hash] = value;
1101 }
1102 // Set the object
11030 return functionCache[hash].bind(object);
1104}
1105
1106/**
1107 * Ensure eval is isolated.
1108 *
1109 * @ignore
1110 * @api private
1111 */
11121var isolateEval = function(functionString) {
1113 // Contains the value we are going to set
11140 var value = null;
1115 // Eval the function
11160 eval("value = " + functionString);
11170 return value;
1118}
1119
1120/**
1121 * Convert Uint8Array to String
1122 *
1123 * @ignore
1124 * @api private
1125 */
11261var convertUint8ArrayToUtf8String = function(byteArray, startIndex, endIndex) {
11270 return BinaryParser.decode_utf8(convertArraytoUtf8BinaryString(byteArray, startIndex, endIndex));
1128}
1129
11301var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) {
11310 var result = "";
11320 for(var i = startIndex; i < endIndex; i++) {
11330 result = result + String.fromCharCode(byteArray[i]);
1134 }
1135
11360 return result;
1137};
1138
1139/**
1140 * Deserialize data as BSON.
1141 *
1142 * Options
1143 * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized.
1144 * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse.
1145 * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function.
1146 * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits
1147 *
1148 * @param {Buffer} buffer the buffer containing the serialized set of BSON documents.
1149 * @param {Object} [options] additional options used for the deserialization.
1150 * @param {Boolean} [isArray] ignore used for recursive parsing.
1151 * @return {Object} returns the deserialized Javascript Object.
1152 * @api public
1153 */
11541BSON.deserialize = function(buffer, options, isArray) {
1155 // Options
11560 options = options == null ? {} : options;
11570 var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
11580 var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions'];
11590 var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32'];
11600 var promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs'];
1161
1162 // Validate that we have at least 4 bytes of buffer
11630 if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long");
1164
1165 // Set up index
11660 var index = typeof options['index'] == 'number' ? options['index'] : 0;
1167 // Reads in a C style string
11680 var readCStyleString = function() {
1169 // Get the start search index
11700 var i = index;
1171 // Locate the end of the c string
11720 while(buffer[i] !== 0x00 && i < buffer.length) {
11730 i++
1174 }
1175 // If are at the end of the buffer there is a problem with the document
11760 if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
1177 // Grab utf8 encoded string
11780 var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, i) : convertUint8ArrayToUtf8String(buffer, index, i);
1179 // Update index position
11800 index = i + 1;
1181 // Return string
11820 return string;
1183 }
1184
1185 // Create holding object
11860 var object = isArray ? [] : {};
1187
1188 // Read the document size
11890 var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1190
1191 // Ensure buffer is valid size
11920 if(size < 5 || size > buffer.length) throw new Error("corrupt bson message");
1193
1194 // While we have more left data left keep parsing
11950 while(true) {
1196 // Read the type
11970 var elementType = buffer[index++];
1198 // If we get a zero it's the last byte, exit
11990 if(elementType == 0) break;
1200 // Read the name of the field
12010 var name = readCStyleString();
1202 // Switch on the type
12030 switch(elementType) {
1204 case BSON.BSON_DATA_OID:
12050 var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('binary', index, index + 12) : convertArraytoUtf8BinaryString(buffer, index, index + 12);
1206 // Decode the oid
12070 object[name] = new ObjectID(string);
1208 // Update index
12090 index = index + 12;
12100 break;
1211 case BSON.BSON_DATA_STRING:
1212 // Read the content of the field
12130 var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1214 // Add string to object
12150 object[name] = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1);
1216 // Update parse index position
12170 index = index + stringSize;
12180 break;
1219 case BSON.BSON_DATA_INT:
1220 // Decode the 32bit value
12210 object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
12220 break;
1223 case BSON.BSON_DATA_NUMBER:
1224 // Decode the double value
12250 object[name] = readIEEE754(buffer, index, 'little', 52, 8);
1226 // Update the index
12270 index = index + 8;
12280 break;
1229 case BSON.BSON_DATA_DATE:
1230 // Unpack the low and high bits
12310 var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
12320 var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1233 // Set date object
12340 object[name] = new Date(new Long(lowBits, highBits).toNumber());
12350 break;
1236 case BSON.BSON_DATA_BOOLEAN:
1237 // Parse the boolean value
12380 object[name] = buffer[index++] == 1;
12390 break;
1240 case BSON.BSON_DATA_NULL:
1241 // Parse the boolean value
12420 object[name] = null;
12430 break;
1244 case BSON.BSON_DATA_BINARY:
1245 // Decode the size of the binary blob
12460 var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1247 // Decode the subtype
12480 var subType = buffer[index++];
1249 // Decode as raw Buffer object if options specifies it
12500 if(buffer['slice'] != null) {
1251 // If we have subtype 2 skip the 4 bytes for the size
12520 if(subType == Binary.SUBTYPE_BYTE_ARRAY) {
12530 binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1254 }
1255 // Slice the data
12560 object[name] = new Binary(buffer.slice(index, index + binarySize), subType);
1257 } else {
12580 var _buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(binarySize)) : new Array(binarySize);
1259 // If we have subtype 2 skip the 4 bytes for the size
12600 if(subType == Binary.SUBTYPE_BYTE_ARRAY) {
12610 binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1262 }
1263 // Copy the data
12640 for(var i = 0; i < binarySize; i++) {
12650 _buffer[i] = buffer[index + i];
1266 }
1267 // Create the binary object
12680 object[name] = new Binary(_buffer, subType);
1269 }
1270 // Update the index
12710 index = index + binarySize;
12720 break;
1273 case BSON.BSON_DATA_ARRAY:
12740 options['index'] = index;
1275 // Decode the size of the array document
12760 var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
1277 // Set the array to the object
12780 object[name] = BSON.deserialize(buffer, options, true);
1279 // Adjust the index
12800 index = index + objectSize;
12810 break;
1282 case BSON.BSON_DATA_OBJECT:
12830 options['index'] = index;
1284 // Decode the size of the object document
12850 var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
1286 // Set the array to the object
12870 object[name] = BSON.deserialize(buffer, options, false);
1288 // Adjust the index
12890 index = index + objectSize;
12900 break;
1291 case BSON.BSON_DATA_REGEXP:
1292 // Create the regexp
12930 var source = readCStyleString();
12940 var regExpOptions = readCStyleString();
1295 // For each option add the corresponding one for javascript
12960 var optionsArray = new Array(regExpOptions.length);
1297
1298 // Parse options
12990 for(var i = 0; i < regExpOptions.length; i++) {
13000 switch(regExpOptions[i]) {
1301 case 'm':
13020 optionsArray[i] = 'm';
13030 break;
1304 case 's':
13050 optionsArray[i] = 'g';
13060 break;
1307 case 'i':
13080 optionsArray[i] = 'i';
13090 break;
1310 }
1311 }
1312
13130 object[name] = new RegExp(source, optionsArray.join(''));
13140 break;
1315 case BSON.BSON_DATA_LONG:
1316 // Unpack the low and high bits
13170 var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
13180 var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1319 // Create long object
13200 var long = new Long(lowBits, highBits);
1321 // Promote the long if possible
13220 if(promoteLongs) {
13230 object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long;
1324 } else {
13250 object[name] = long;
1326 }
13270 break;
1328 case BSON.BSON_DATA_SYMBOL:
1329 // Read the content of the field
13300 var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1331 // Add string to object
13320 object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1));
1333 // Update parse index position
13340 index = index + stringSize;
13350 break;
1336 case BSON.BSON_DATA_TIMESTAMP:
1337 // Unpack the low and high bits
13380 var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
13390 var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1340 // Set the object
13410 object[name] = new Timestamp(lowBits, highBits);
13420 break;
1343 case BSON.BSON_DATA_MIN_KEY:
1344 // Parse the object
13450 object[name] = new MinKey();
13460 break;
1347 case BSON.BSON_DATA_MAX_KEY:
1348 // Parse the object
13490 object[name] = new MaxKey();
13500 break;
1351 case BSON.BSON_DATA_CODE:
1352 // Read the content of the field
13530 var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1354 // Function string
13550 var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1);
1356
1357 // If we are evaluating the functions
13580 if(evalFunctions) {
1359 // Contains the value we are going to set
13600 var value = null;
1361 // If we have cache enabled let's look for the md5 of the function in the cache
13620 if(cacheFunctions) {
13630 var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString;
1364 // Got to do this to avoid V8 deoptimizing the call due to finding eval
13650 object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
1366 } else {
1367 // Set directly
13680 object[name] = isolateEval(functionString);
1369 }
1370 } else {
13710 object[name] = new Code(functionString, {});
1372 }
1373
1374 // Update parse index position
13750 index = index + stringSize;
13760 break;
1377 case BSON.BSON_DATA_CODE_W_SCOPE:
1378 // Read the content of the field
13790 var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
13800 var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1381 // Javascript function
13820 var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1);
1383 // Update parse index position
13840 index = index + stringSize;
1385 // Parse the element
13860 options['index'] = index;
1387 // Decode the size of the object document
13880 var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
1389 // Decode the scope object
13900 var scopeObject = BSON.deserialize(buffer, options, false);
1391 // Adjust the index
13920 index = index + objectSize;
1393
1394 // If we are evaluating the functions
13950 if(evalFunctions) {
1396 // Contains the value we are going to set
13970 var value = null;
1398 // If we have cache enabled let's look for the md5 of the function in the cache
13990 if(cacheFunctions) {
14000 var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString;
1401 // Got to do this to avoid V8 deoptimizing the call due to finding eval
14020 object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
1403 } else {
1404 // Set directly
14050 object[name] = isolateEval(functionString);
1406 }
1407
1408 // Set the scope on the object
14090 object[name].scope = scopeObject;
1410 } else {
14110 object[name] = new Code(functionString, scopeObject);
1412 }
1413
1414 // Add string to object
14150 break;
1416 }
1417 }
1418
1419 // Check if we have a db ref object
14200 if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']);
1421
1422 // Return the final objects
14230 return object;
1424}
1425
1426/**
1427 * Check if key name is valid.
1428 *
1429 * @ignore
1430 * @api private
1431 */
14321BSON.checkKey = function checkKey (key, dollarsAndDotsOk) {
14330 if (!key.length) return;
1434 // Check if we have a legal key for the object
14350 if (!!~key.indexOf("\x00")) {
1436 // The BSON spec doesn't allow keys with null bytes because keys are
1437 // null-terminated.
14380 throw Error("key " + key + " must not contain null bytes");
1439 }
14400 if (!dollarsAndDotsOk) {
14410 if('$' == key[0]) {
14420 throw Error("key " + key + " must not start with '$'");
14430 } else if (!!~key.indexOf('.')) {
14440 throw Error("key " + key + " must not contain '.'");
1445 }
1446 }
1447};
1448
1449/**
1450 * Deserialize data as BSON.
1451 *
1452 * Options
1453 * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized.
1454 * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse.
1455 * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function.
1456 *
1457 * @param {Buffer} buffer the buffer containing the serialized set of BSON documents.
1458 * @param {Object} [options] additional options used for the deserialization.
1459 * @param {Boolean} [isArray] ignore used for recursive parsing.
1460 * @return {Object} returns the deserialized Javascript Object.
1461 * @api public
1462 */
14631BSON.prototype.deserialize = function(data, options) {
14640 return BSON.deserialize(data, options);
1465}
1466
1467/**
1468 * Deserialize stream data as BSON documents.
1469 *
1470 * Options
1471 * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized.
1472 * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse.
1473 * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function.
1474 *
1475 * @param {Buffer} data the buffer containing the serialized set of BSON documents.
1476 * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start.
1477 * @param {Number} numberOfDocuments number of documents to deserialize.
1478 * @param {Array} documents an array where to store the deserialized documents.
1479 * @param {Number} docStartIndex the index in the documents array from where to start inserting documents.
1480 * @param {Object} [options] additional options used for the deserialization.
1481 * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents.
1482 * @api public
1483 */
14841BSON.prototype.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) {
14850 return BSON.deserializeStream(data, startIndex, numberOfDocuments, documents, docStartIndex, options);
1486}
1487
1488/**
1489 * Serialize a Javascript object.
1490 *
1491 * @param {Object} object the Javascript object to serialize.
1492 * @param {Boolean} checkKeys the serializer will check if keys are valid.
1493 * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**.
1494 * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**.
1495 * @return {Buffer} returns the Buffer object containing the serialized object.
1496 * @api public
1497 */
14981BSON.prototype.serialize = function(object, checkKeys, asBuffer, serializeFunctions) {
14990 return BSON.serialize(object, checkKeys, asBuffer, serializeFunctions);
1500}
1501
1502/**
1503 * Calculate the bson size for a passed in Javascript object.
1504 *
1505 * @param {Object} object the Javascript object to calculate the BSON byte size for.
1506 * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**.
1507 * @return {Number} returns the number of bytes the BSON object will take up.
1508 * @api public
1509 */
15101BSON.prototype.calculateObjectSize = function(object, serializeFunctions) {
15110 return BSON.calculateObjectSize(object, serializeFunctions);
1512}
1513
1514/**
1515 * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization.
1516 *
1517 * @param {Object} object the Javascript object to serialize.
1518 * @param {Boolean} checkKeys the serializer will check if keys are valid.
1519 * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object.
1520 * @param {Number} index the index in the buffer where we wish to start serializing into.
1521 * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**.
1522 * @return {Number} returns the new write index in the Buffer.
1523 * @api public
1524 */
15251BSON.prototype.serializeWithBufferAndIndex = function(object, checkKeys, buffer, startIndex, serializeFunctions) {
15260 return BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, startIndex, serializeFunctions);
1527}
1528
1529/**
1530 * @ignore
1531 * @api private
1532 */
15331exports.Code = Code;
15341exports.Symbol = Symbol;
15351exports.BSON = BSON;
15361exports.DBRef = DBRef;
15371exports.Binary = Binary;
15381exports.ObjectID = ObjectID;
15391exports.Long = Long;
15401exports.Timestamp = Timestamp;
15411exports.Double = Double;
15421exports.MinKey = MinKey;
15431exports.MaxKey = MaxKey;
1544

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/code.js

37%
8
3
5
LineHitsSource
1/**
2 * A class representation of the BSON Code type.
3 *
4 * @class Represents the BSON Code type.
5 * @param {String|Function} code a string or function.
6 * @param {Object} [scope] an optional scope for the function.
7 * @return {Code}
8 */
91function Code(code, scope) {
100 if(!(this instanceof Code)) return new Code(code, scope);
11
120 this._bsontype = 'Code';
130 this.code = code;
140 this.scope = scope == null ? {} : scope;
15};
16
17/**
18 * @ignore
19 * @api private
20 */
211Code.prototype.toJSON = function() {
220 return {scope:this.scope, code:this.code};
23}
24
251exports.Code = Code;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js

33%
9
3
6
LineHitsSource
1/**
2 * A class representation of the BSON DBRef type.
3 *
4 * @class Represents the BSON DBRef type.
5 * @param {String} namespace the collection name.
6 * @param {ObjectID} oid the reference ObjectID.
7 * @param {String} [db] optional db name, if omitted the reference is local to the current db.
8 * @return {DBRef}
9 */
101function DBRef(namespace, oid, db) {
110 if(!(this instanceof DBRef)) return new DBRef(namespace, oid, db);
12
130 this._bsontype = 'DBRef';
140 this.namespace = namespace;
150 this.oid = oid;
160 this.db = db;
17};
18
19/**
20 * @ignore
21 * @api private
22 */
231DBRef.prototype.toJSON = function() {
240 return {
25 '$ref':this.namespace,
26 '$id':this.oid,
27 '$db':this.db == null ? '' : this.db
28 };
29}
30
311exports.DBRef = DBRef;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/double.js

44%
9
4
5
LineHitsSource
1/**
2 * A class representation of the BSON Double type.
3 *
4 * @class Represents the BSON Double type.
5 * @param {Number} value the number we want to represent as a double.
6 * @return {Double}
7 */
81function Double(value) {
90 if(!(this instanceof Double)) return new Double(value);
10
110 this._bsontype = 'Double';
120 this.value = value;
13}
14
15/**
16 * Access the number value.
17 *
18 * @return {Number} returns the wrapped double number.
19 * @api public
20 */
211Double.prototype.valueOf = function() {
220 return this.value;
23};
24
25/**
26 * @ignore
27 * @api private
28 */
291Double.prototype.toJSON = function() {
300 return this.value;
31}
32
331exports.Double = Double;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js

8%
49
4
45
LineHitsSource
1// Copyright (c) 2008, Fair Oaks Labs, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
15// may be used to endorse or promote products derived from this software
16// without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30//
31// Modifications to writeIEEE754 to support negative zeroes made by Brian White
32
331var readIEEE754 = function(buffer, offset, endian, mLen, nBytes) {
340 var e, m,
35 bBE = (endian === 'big'),
36 eLen = nBytes * 8 - mLen - 1,
37 eMax = (1 << eLen) - 1,
38 eBias = eMax >> 1,
39 nBits = -7,
40 i = bBE ? 0 : (nBytes - 1),
41 d = bBE ? 1 : -1,
42 s = buffer[offset + i];
43
440 i += d;
45
460 e = s & ((1 << (-nBits)) - 1);
470 s >>= (-nBits);
480 nBits += eLen;
490 for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
50
510 m = e & ((1 << (-nBits)) - 1);
520 e >>= (-nBits);
530 nBits += mLen;
540 for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
55
560 if (e === 0) {
570 e = 1 - eBias;
580 } else if (e === eMax) {
590 return m ? NaN : ((s ? -1 : 1) * Infinity);
60 } else {
610 m = m + Math.pow(2, mLen);
620 e = e - eBias;
63 }
640 return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
65};
66
671var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) {
680 var e, m, c,
69 bBE = (endian === 'big'),
70 eLen = nBytes * 8 - mLen - 1,
71 eMax = (1 << eLen) - 1,
72 eBias = eMax >> 1,
73 rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
74 i = bBE ? (nBytes-1) : 0,
75 d = bBE ? -1 : 1,
76 s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
77
780 value = Math.abs(value);
79
800 if (isNaN(value) || value === Infinity) {
810 m = isNaN(value) ? 1 : 0;
820 e = eMax;
83 } else {
840 e = Math.floor(Math.log(value) / Math.LN2);
850 if (value * (c = Math.pow(2, -e)) < 1) {
860 e--;
870 c *= 2;
88 }
890 if (e+eBias >= 1) {
900 value += rt / c;
91 } else {
920 value += rt * Math.pow(2, 1 - eBias);
93 }
940 if (value * c >= 2) {
950 e++;
960 c /= 2;
97 }
98
990 if (e + eBias >= eMax) {
1000 m = 0;
1010 e = eMax;
1020 } else if (e + eBias >= 1) {
1030 m = (value * c - 1) * Math.pow(2, mLen);
1040 e = e + eBias;
105 } else {
1060 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
1070 e = 0;
108 }
109 }
110
1110 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
112
1130 e = (e << mLen) | m;
1140 eLen += mLen;
1150 for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
116
1170 buffer[offset + i - d] |= s * 128;
118};
119
1201exports.readIEEE754 = readIEEE754;
1211exports.writeIEEE754 = writeIEEE754;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/index.js

42%
21
9
12
LineHitsSource
11try {
21 exports.BSONPure = require('./bson');
31 exports.BSONNative = require('../../ext');
4} catch(err) {
5 // do nothing
6}
7
81[ './binary_parser'
9 , './binary'
10 , './code'
11 , './db_ref'
12 , './double'
13 , './max_key'
14 , './min_key'
15 , './objectid'
16 , './symbol'
17 , './timestamp'
18 , './long'].forEach(function (path) {
1911 var module = require('./' + path);
2011 for (var i in module) {
2112 exports[i] = module[i];
22 }
23});
24
25// Exports all the classes for the NATIVE JS BSON Parser
261exports.native = function() {
270 var classes = {};
28 // Map all the classes
290 [ './binary_parser'
30 , './binary'
31 , './code'
32 , './db_ref'
33 , './double'
34 , './max_key'
35 , './min_key'
36 , './objectid'
37 , './symbol'
38 , './timestamp'
39 , './long'
40 , '../../ext'
41].forEach(function (path) {
420 var module = require('./' + path);
430 for (var i in module) {
440 classes[i] = module[i];
45 }
46 });
47 // Return classes list
480 return classes;
49}
50
51// Exports all the classes for the PURE JS BSON Parser
521exports.pure = function() {
530 var classes = {};
54 // Map all the classes
550 [ './binary_parser'
56 , './binary'
57 , './code'
58 , './db_ref'
59 , './double'
60 , './max_key'
61 , './min_key'
62 , './objectid'
63 , './symbol'
64 , './timestamp'
65 , './long'
66 , '././bson'].forEach(function (path) {
670 var module = require('./' + path);
680 for (var i in module) {
690 classes[i] = module[i];
70 }
71 });
72 // Return classes list
730 return classes;
74}
75

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/long.js

31%
296
94
202
LineHitsSource
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// Copyright 2009 Google Inc. All Rights Reserved
14
15/**
16 * Defines a Long class for representing a 64-bit two's-complement
17 * integer value, which faithfully simulates the behavior of a Java "Long". This
18 * implementation is derived from LongLib in GWT.
19 *
20 * Constructs a 64-bit two's-complement integer, given its low and high 32-bit
21 * values as *signed* integers. See the from* functions below for more
22 * convenient ways of constructing Longs.
23 *
24 * The internal representation of a Long is the two given signed, 32-bit values.
25 * We use 32-bit pieces because these are the size of integers on which
26 * Javascript performs bit-operations. For operations like addition and
27 * multiplication, we split each number into 16-bit pieces, which can easily be
28 * multiplied within Javascript's floating-point representation without overflow
29 * or change in sign.
30 *
31 * In the algorithms below, we frequently reduce the negative case to the
32 * positive case by negating the input(s) and then post-processing the result.
33 * Note that we must ALWAYS check specially whether those values are MIN_VALUE
34 * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
35 * a positive number, it overflows back into a negative). Not handling this
36 * case would often result in infinite recursion.
37 *
38 * @class Represents the BSON Long type.
39 * @param {Number} low the low (signed) 32 bits of the Long.
40 * @param {Number} high the high (signed) 32 bits of the Long.
41 */
421function Long(low, high) {
4310 if(!(this instanceof Long)) return new Long(low, high);
44
4510 this._bsontype = 'Long';
46 /**
47 * @type {number}
48 * @api private
49 */
5010 this.low_ = low | 0; // force into 32 signed bits.
51
52 /**
53 * @type {number}
54 * @api private
55 */
5610 this.high_ = high | 0; // force into 32 signed bits.
57};
58
59/**
60 * Return the int value.
61 *
62 * @return {Number} the value, assuming it is a 32-bit integer.
63 * @api public
64 */
651Long.prototype.toInt = function() {
660 return this.low_;
67};
68
69/**
70 * Return the Number value.
71 *
72 * @return {Number} the closest floating-point representation to this value.
73 * @api public
74 */
751Long.prototype.toNumber = function() {
760 return this.high_ * Long.TWO_PWR_32_DBL_ +
77 this.getLowBitsUnsigned();
78};
79
80/**
81 * Return the JSON value.
82 *
83 * @return {String} the JSON representation.
84 * @api public
85 */
861Long.prototype.toJSON = function() {
870 return this.toString();
88}
89
90/**
91 * Return the String value.
92 *
93 * @param {Number} [opt_radix] the radix in which the text should be written.
94 * @return {String} the textual representation of this value.
95 * @api public
96 */
971Long.prototype.toString = function(opt_radix) {
980 var radix = opt_radix || 10;
990 if (radix < 2 || 36 < radix) {
1000 throw Error('radix out of range: ' + radix);
101 }
102
1030 if (this.isZero()) {
1040 return '0';
105 }
106
1070 if (this.isNegative()) {
1080 if (this.equals(Long.MIN_VALUE)) {
109 // We need to change the Long value before it can be negated, so we remove
110 // the bottom-most digit in this base and then recurse to do the rest.
1110 var radixLong = Long.fromNumber(radix);
1120 var div = this.div(radixLong);
1130 var rem = div.multiply(radixLong).subtract(this);
1140 return div.toString(radix) + rem.toInt().toString(radix);
115 } else {
1160 return '-' + this.negate().toString(radix);
117 }
118 }
119
120 // Do several (6) digits each time through the loop, so as to
121 // minimize the calls to the very expensive emulated div.
1220 var radixToPower = Long.fromNumber(Math.pow(radix, 6));
123
1240 var rem = this;
1250 var result = '';
1260 while (true) {
1270 var remDiv = rem.div(radixToPower);
1280 var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
1290 var digits = intval.toString(radix);
130
1310 rem = remDiv;
1320 if (rem.isZero()) {
1330 return digits + result;
134 } else {
1350 while (digits.length < 6) {
1360 digits = '0' + digits;
137 }
1380 result = '' + digits + result;
139 }
140 }
141};
142
143/**
144 * Return the high 32-bits value.
145 *
146 * @return {Number} the high 32-bits as a signed value.
147 * @api public
148 */
1491Long.prototype.getHighBits = function() {
1500 return this.high_;
151};
152
153/**
154 * Return the low 32-bits value.
155 *
156 * @return {Number} the low 32-bits as a signed value.
157 * @api public
158 */
1591Long.prototype.getLowBits = function() {
1600 return this.low_;
161};
162
163/**
164 * Return the low unsigned 32-bits value.
165 *
166 * @return {Number} the low 32-bits as an unsigned value.
167 * @api public
168 */
1691Long.prototype.getLowBitsUnsigned = function() {
1700 return (this.low_ >= 0) ?
171 this.low_ : Long.TWO_PWR_32_DBL_ + this.low_;
172};
173
174/**
175 * Returns the number of bits needed to represent the absolute value of this Long.
176 *
177 * @return {Number} Returns the number of bits needed to represent the absolute value of this Long.
178 * @api public
179 */
1801Long.prototype.getNumBitsAbs = function() {
1810 if (this.isNegative()) {
1820 if (this.equals(Long.MIN_VALUE)) {
1830 return 64;
184 } else {
1850 return this.negate().getNumBitsAbs();
186 }
187 } else {
1880 var val = this.high_ != 0 ? this.high_ : this.low_;
1890 for (var bit = 31; bit > 0; bit--) {
1900 if ((val & (1 << bit)) != 0) {
1910 break;
192 }
193 }
1940 return this.high_ != 0 ? bit + 33 : bit + 1;
195 }
196};
197
198/**
199 * Return whether this value is zero.
200 *
201 * @return {Boolean} whether this value is zero.
202 * @api public
203 */
2041Long.prototype.isZero = function() {
2050 return this.high_ == 0 && this.low_ == 0;
206};
207
208/**
209 * Return whether this value is negative.
210 *
211 * @return {Boolean} whether this value is negative.
212 * @api public
213 */
2141Long.prototype.isNegative = function() {
2150 return this.high_ < 0;
216};
217
218/**
219 * Return whether this value is odd.
220 *
221 * @return {Boolean} whether this value is odd.
222 * @api public
223 */
2241Long.prototype.isOdd = function() {
2250 return (this.low_ & 1) == 1;
226};
227
228/**
229 * Return whether this Long equals the other
230 *
231 * @param {Long} other Long to compare against.
232 * @return {Boolean} whether this Long equals the other
233 * @api public
234 */
2351Long.prototype.equals = function(other) {
2361 return (this.high_ == other.high_) && (this.low_ == other.low_);
237};
238
239/**
240 * Return whether this Long does not equal the other.
241 *
242 * @param {Long} other Long to compare against.
243 * @return {Boolean} whether this Long does not equal the other.
244 * @api public
245 */
2461Long.prototype.notEquals = function(other) {
2470 return (this.high_ != other.high_) || (this.low_ != other.low_);
248};
249
250/**
251 * Return whether this Long is less than the other.
252 *
253 * @param {Long} other Long to compare against.
254 * @return {Boolean} whether this Long is less than the other.
255 * @api public
256 */
2571Long.prototype.lessThan = function(other) {
2580 return this.compare(other) < 0;
259};
260
261/**
262 * Return whether this Long is less than or equal to the other.
263 *
264 * @param {Long} other Long to compare against.
265 * @return {Boolean} whether this Long is less than or equal to the other.
266 * @api public
267 */
2681Long.prototype.lessThanOrEqual = function(other) {
2690 return this.compare(other) <= 0;
270};
271
272/**
273 * Return whether this Long is greater than the other.
274 *
275 * @param {Long} other Long to compare against.
276 * @return {Boolean} whether this Long is greater than the other.
277 * @api public
278 */
2791Long.prototype.greaterThan = function(other) {
2800 return this.compare(other) > 0;
281};
282
283/**
284 * Return whether this Long is greater than or equal to the other.
285 *
286 * @param {Long} other Long to compare against.
287 * @return {Boolean} whether this Long is greater than or equal to the other.
288 * @api public
289 */
2901Long.prototype.greaterThanOrEqual = function(other) {
2910 return this.compare(other) >= 0;
292};
293
294/**
295 * Compares this Long with the given one.
296 *
297 * @param {Long} other Long to compare against.
298 * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater.
299 * @api public
300 */
3011Long.prototype.compare = function(other) {
3020 if (this.equals(other)) {
3030 return 0;
304 }
305
3060 var thisNeg = this.isNegative();
3070 var otherNeg = other.isNegative();
3080 if (thisNeg && !otherNeg) {
3090 return -1;
310 }
3110 if (!thisNeg && otherNeg) {
3120 return 1;
313 }
314
315 // at this point, the signs are the same, so subtraction will not overflow
3160 if (this.subtract(other).isNegative()) {
3170 return -1;
318 } else {
3190 return 1;
320 }
321};
322
323/**
324 * The negation of this value.
325 *
326 * @return {Long} the negation of this value.
327 * @api public
328 */
3291Long.prototype.negate = function() {
3301 if (this.equals(Long.MIN_VALUE)) {
3310 return Long.MIN_VALUE;
332 } else {
3331 return this.not().add(Long.ONE);
334 }
335};
336
337/**
338 * Returns the sum of this and the given Long.
339 *
340 * @param {Long} other Long to add to this one.
341 * @return {Long} the sum of this and the given Long.
342 * @api public
343 */
3441Long.prototype.add = function(other) {
345 // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
346
3471 var a48 = this.high_ >>> 16;
3481 var a32 = this.high_ & 0xFFFF;
3491 var a16 = this.low_ >>> 16;
3501 var a00 = this.low_ & 0xFFFF;
351
3521 var b48 = other.high_ >>> 16;
3531 var b32 = other.high_ & 0xFFFF;
3541 var b16 = other.low_ >>> 16;
3551 var b00 = other.low_ & 0xFFFF;
356
3571 var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
3581 c00 += a00 + b00;
3591 c16 += c00 >>> 16;
3601 c00 &= 0xFFFF;
3611 c16 += a16 + b16;
3621 c32 += c16 >>> 16;
3631 c16 &= 0xFFFF;
3641 c32 += a32 + b32;
3651 c48 += c32 >>> 16;
3661 c32 &= 0xFFFF;
3671 c48 += a48 + b48;
3681 c48 &= 0xFFFF;
3691 return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
370};
371
372/**
373 * Returns the difference of this and the given Long.
374 *
375 * @param {Long} other Long to subtract from this.
376 * @return {Long} the difference of this and the given Long.
377 * @api public
378 */
3791Long.prototype.subtract = function(other) {
3800 return this.add(other.negate());
381};
382
383/**
384 * Returns the product of this and the given Long.
385 *
386 * @param {Long} other Long to multiply with this.
387 * @return {Long} the product of this and the other.
388 * @api public
389 */
3901Long.prototype.multiply = function(other) {
3910 if (this.isZero()) {
3920 return Long.ZERO;
3930 } else if (other.isZero()) {
3940 return Long.ZERO;
395 }
396
3970 if (this.equals(Long.MIN_VALUE)) {
3980 return other.isOdd() ? Long.MIN_VALUE : Long.ZERO;
3990 } else if (other.equals(Long.MIN_VALUE)) {
4000 return this.isOdd() ? Long.MIN_VALUE : Long.ZERO;
401 }
402
4030 if (this.isNegative()) {
4040 if (other.isNegative()) {
4050 return this.negate().multiply(other.negate());
406 } else {
4070 return this.negate().multiply(other).negate();
408 }
4090 } else if (other.isNegative()) {
4100 return this.multiply(other.negate()).negate();
411 }
412
413 // If both Longs are small, use float multiplication
4140 if (this.lessThan(Long.TWO_PWR_24_) &&
415 other.lessThan(Long.TWO_PWR_24_)) {
4160 return Long.fromNumber(this.toNumber() * other.toNumber());
417 }
418
419 // Divide each Long into 4 chunks of 16 bits, and then add up 4x4 products.
420 // We can skip products that would overflow.
421
4220 var a48 = this.high_ >>> 16;
4230 var a32 = this.high_ & 0xFFFF;
4240 var a16 = this.low_ >>> 16;
4250 var a00 = this.low_ & 0xFFFF;
426
4270 var b48 = other.high_ >>> 16;
4280 var b32 = other.high_ & 0xFFFF;
4290 var b16 = other.low_ >>> 16;
4300 var b00 = other.low_ & 0xFFFF;
431
4320 var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
4330 c00 += a00 * b00;
4340 c16 += c00 >>> 16;
4350 c00 &= 0xFFFF;
4360 c16 += a16 * b00;
4370 c32 += c16 >>> 16;
4380 c16 &= 0xFFFF;
4390 c16 += a00 * b16;
4400 c32 += c16 >>> 16;
4410 c16 &= 0xFFFF;
4420 c32 += a32 * b00;
4430 c48 += c32 >>> 16;
4440 c32 &= 0xFFFF;
4450 c32 += a16 * b16;
4460 c48 += c32 >>> 16;
4470 c32 &= 0xFFFF;
4480 c32 += a00 * b32;
4490 c48 += c32 >>> 16;
4500 c32 &= 0xFFFF;
4510 c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
4520 c48 &= 0xFFFF;
4530 return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
454};
455
456/**
457 * Returns this Long divided by the given one.
458 *
459 * @param {Long} other Long by which to divide.
460 * @return {Long} this Long divided by the given one.
461 * @api public
462 */
4631Long.prototype.div = function(other) {
4640 if (other.isZero()) {
4650 throw Error('division by zero');
4660 } else if (this.isZero()) {
4670 return Long.ZERO;
468 }
469
4700 if (this.equals(Long.MIN_VALUE)) {
4710 if (other.equals(Long.ONE) ||
472 other.equals(Long.NEG_ONE)) {
4730 return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
4740 } else if (other.equals(Long.MIN_VALUE)) {
4750 return Long.ONE;
476 } else {
477 // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
4780 var halfThis = this.shiftRight(1);
4790 var approx = halfThis.div(other).shiftLeft(1);
4800 if (approx.equals(Long.ZERO)) {
4810 return other.isNegative() ? Long.ONE : Long.NEG_ONE;
482 } else {
4830 var rem = this.subtract(other.multiply(approx));
4840 var result = approx.add(rem.div(other));
4850 return result;
486 }
487 }
4880 } else if (other.equals(Long.MIN_VALUE)) {
4890 return Long.ZERO;
490 }
491
4920 if (this.isNegative()) {
4930 if (other.isNegative()) {
4940 return this.negate().div(other.negate());
495 } else {
4960 return this.negate().div(other).negate();
497 }
4980 } else if (other.isNegative()) {
4990 return this.div(other.negate()).negate();
500 }
501
502 // Repeat the following until the remainder is less than other: find a
503 // floating-point that approximates remainder / other *from below*, add this
504 // into the result, and subtract it from the remainder. It is critical that
505 // the approximate value is less than or equal to the real value so that the
506 // remainder never becomes negative.
5070 var res = Long.ZERO;
5080 var rem = this;
5090 while (rem.greaterThanOrEqual(other)) {
510 // Approximate the result of division. This may be a little greater or
511 // smaller than the actual value.
5120 var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
513
514 // We will tweak the approximate result by changing it in the 48-th digit or
515 // the smallest non-fractional digit, whichever is larger.
5160 var log2 = Math.ceil(Math.log(approx) / Math.LN2);
5170 var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
518
519 // Decrease the approximation until it is smaller than the remainder. Note
520 // that if it is too large, the product overflows and is negative.
5210 var approxRes = Long.fromNumber(approx);
5220 var approxRem = approxRes.multiply(other);
5230 while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
5240 approx -= delta;
5250 approxRes = Long.fromNumber(approx);
5260 approxRem = approxRes.multiply(other);
527 }
528
529 // We know the answer can't be zero... and actually, zero would cause
530 // infinite recursion since we would make no progress.
5310 if (approxRes.isZero()) {
5320 approxRes = Long.ONE;
533 }
534
5350 res = res.add(approxRes);
5360 rem = rem.subtract(approxRem);
537 }
5380 return res;
539};
540
541/**
542 * Returns this Long modulo the given one.
543 *
544 * @param {Long} other Long by which to mod.
545 * @return {Long} this Long modulo the given one.
546 * @api public
547 */
5481Long.prototype.modulo = function(other) {
5490 return this.subtract(this.div(other).multiply(other));
550};
551
552/**
553 * The bitwise-NOT of this value.
554 *
555 * @return {Long} the bitwise-NOT of this value.
556 * @api public
557 */
5581Long.prototype.not = function() {
5591 return Long.fromBits(~this.low_, ~this.high_);
560};
561
562/**
563 * Returns the bitwise-AND of this Long and the given one.
564 *
565 * @param {Long} other the Long with which to AND.
566 * @return {Long} the bitwise-AND of this and the other.
567 * @api public
568 */
5691Long.prototype.and = function(other) {
5700 return Long.fromBits(this.low_ & other.low_, this.high_ & other.high_);
571};
572
573/**
574 * Returns the bitwise-OR of this Long and the given one.
575 *
576 * @param {Long} other the Long with which to OR.
577 * @return {Long} the bitwise-OR of this and the other.
578 * @api public
579 */
5801Long.prototype.or = function(other) {
5810 return Long.fromBits(this.low_ | other.low_, this.high_ | other.high_);
582};
583
584/**
585 * Returns the bitwise-XOR of this Long and the given one.
586 *
587 * @param {Long} other the Long with which to XOR.
588 * @return {Long} the bitwise-XOR of this and the other.
589 * @api public
590 */
5911Long.prototype.xor = function(other) {
5920 return Long.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_);
593};
594
595/**
596 * Returns this Long with bits shifted to the left by the given amount.
597 *
598 * @param {Number} numBits the number of bits by which to shift.
599 * @return {Long} this shifted to the left by the given amount.
600 * @api public
601 */
6021Long.prototype.shiftLeft = function(numBits) {
6030 numBits &= 63;
6040 if (numBits == 0) {
6050 return this;
606 } else {
6070 var low = this.low_;
6080 if (numBits < 32) {
6090 var high = this.high_;
6100 return Long.fromBits(
611 low << numBits,
612 (high << numBits) | (low >>> (32 - numBits)));
613 } else {
6140 return Long.fromBits(0, low << (numBits - 32));
615 }
616 }
617};
618
619/**
620 * Returns this Long with bits shifted to the right by the given amount.
621 *
622 * @param {Number} numBits the number of bits by which to shift.
623 * @return {Long} this shifted to the right by the given amount.
624 * @api public
625 */
6261Long.prototype.shiftRight = function(numBits) {
6270 numBits &= 63;
6280 if (numBits == 0) {
6290 return this;
630 } else {
6310 var high = this.high_;
6320 if (numBits < 32) {
6330 var low = this.low_;
6340 return Long.fromBits(
635 (low >>> numBits) | (high << (32 - numBits)),
636 high >> numBits);
637 } else {
6380 return Long.fromBits(
639 high >> (numBits - 32),
640 high >= 0 ? 0 : -1);
641 }
642 }
643};
644
645/**
646 * Returns this Long with bits shifted to the right by the given amount, with the new top bits matching the current sign bit.
647 *
648 * @param {Number} numBits the number of bits by which to shift.
649 * @return {Long} this shifted to the right by the given amount, with zeros placed into the new leading bits.
650 * @api public
651 */
6521Long.prototype.shiftRightUnsigned = function(numBits) {
6530 numBits &= 63;
6540 if (numBits == 0) {
6550 return this;
656 } else {
6570 var high = this.high_;
6580 if (numBits < 32) {
6590 var low = this.low_;
6600 return Long.fromBits(
661 (low >>> numBits) | (high << (32 - numBits)),
662 high >>> numBits);
6630 } else if (numBits == 32) {
6640 return Long.fromBits(high, 0);
665 } else {
6660 return Long.fromBits(high >>> (numBits - 32), 0);
667 }
668 }
669};
670
671/**
672 * Returns a Long representing the given (32-bit) integer value.
673 *
674 * @param {Number} value the 32-bit integer in question.
675 * @return {Long} the corresponding Long value.
676 * @api public
677 */
6781Long.fromInt = function(value) {
6794 if (-128 <= value && value < 128) {
6803 var cachedObj = Long.INT_CACHE_[value];
6813 if (cachedObj) {
6820 return cachedObj;
683 }
684 }
685
6864 var obj = new Long(value | 0, value < 0 ? -1 : 0);
6874 if (-128 <= value && value < 128) {
6883 Long.INT_CACHE_[value] = obj;
689 }
6904 return obj;
691};
692
693/**
694 * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
695 *
696 * @param {Number} value the number in question.
697 * @return {Long} the corresponding Long value.
698 * @api public
699 */
7001Long.fromNumber = function(value) {
7013 if (isNaN(value) || !isFinite(value)) {
7020 return Long.ZERO;
7033 } else if (value <= -Long.TWO_PWR_63_DBL_) {
7040 return Long.MIN_VALUE;
7053 } else if (value + 1 >= Long.TWO_PWR_63_DBL_) {
7060 return Long.MAX_VALUE;
7073 } else if (value < 0) {
7081 return Long.fromNumber(-value).negate();
709 } else {
7102 return new Long(
711 (value % Long.TWO_PWR_32_DBL_) | 0,
712 (value / Long.TWO_PWR_32_DBL_) | 0);
713 }
714};
715
716/**
717 * Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits.
718 *
719 * @param {Number} lowBits the low 32-bits.
720 * @param {Number} highBits the high 32-bits.
721 * @return {Long} the corresponding Long value.
722 * @api public
723 */
7241Long.fromBits = function(lowBits, highBits) {
7254 return new Long(lowBits, highBits);
726};
727
728/**
729 * Returns a Long representation of the given string, written using the given radix.
730 *
731 * @param {String} str the textual representation of the Long.
732 * @param {Number} opt_radix the radix in which the text is written.
733 * @return {Long} the corresponding Long value.
734 * @api public
735 */
7361Long.fromString = function(str, opt_radix) {
7370 if (str.length == 0) {
7380 throw Error('number format error: empty string');
739 }
740
7410 var radix = opt_radix || 10;
7420 if (radix < 2 || 36 < radix) {
7430 throw Error('radix out of range: ' + radix);
744 }
745
7460 if (str.charAt(0) == '-') {
7470 return Long.fromString(str.substring(1), radix).negate();
7480 } else if (str.indexOf('-') >= 0) {
7490 throw Error('number format error: interior "-" character: ' + str);
750 }
751
752 // Do several (8) digits each time through the loop, so as to
753 // minimize the calls to the very expensive emulated div.
7540 var radixToPower = Long.fromNumber(Math.pow(radix, 8));
755
7560 var result = Long.ZERO;
7570 for (var i = 0; i < str.length; i += 8) {
7580 var size = Math.min(8, str.length - i);
7590 var value = parseInt(str.substring(i, i + size), radix);
7600 if (size < 8) {
7610 var power = Long.fromNumber(Math.pow(radix, size));
7620 result = result.multiply(power).add(Long.fromNumber(value));
763 } else {
7640 result = result.multiply(radixToPower);
7650 result = result.add(Long.fromNumber(value));
766 }
767 }
7680 return result;
769};
770
771// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
772// from* methods on which they depend.
773
774
775/**
776 * A cache of the Long representations of small integer values.
777 * @type {Object}
778 * @api private
779 */
7801Long.INT_CACHE_ = {};
781
782// NOTE: the compiler should inline these constant values below and then remove
783// these variables, so there should be no runtime penalty for these.
784
785/**
786 * Number used repeated below in calculations. This must appear before the
787 * first call to any from* function below.
788 * @type {number}
789 * @api private
790 */
7911Long.TWO_PWR_16_DBL_ = 1 << 16;
792
793/**
794 * @type {number}
795 * @api private
796 */
7971Long.TWO_PWR_24_DBL_ = 1 << 24;
798
799/**
800 * @type {number}
801 * @api private
802 */
8031Long.TWO_PWR_32_DBL_ = Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_;
804
805/**
806 * @type {number}
807 * @api private
808 */
8091Long.TWO_PWR_31_DBL_ = Long.TWO_PWR_32_DBL_ / 2;
810
811/**
812 * @type {number}
813 * @api private
814 */
8151Long.TWO_PWR_48_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_;
816
817/**
818 * @type {number}
819 * @api private
820 */
8211Long.TWO_PWR_64_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_;
822
823/**
824 * @type {number}
825 * @api private
826 */
8271Long.TWO_PWR_63_DBL_ = Long.TWO_PWR_64_DBL_ / 2;
828
829/** @type {Long} */
8301Long.ZERO = Long.fromInt(0);
831
832/** @type {Long} */
8331Long.ONE = Long.fromInt(1);
834
835/** @type {Long} */
8361Long.NEG_ONE = Long.fromInt(-1);
837
838/** @type {Long} */
8391Long.MAX_VALUE =
840 Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0);
841
842/** @type {Long} */
8431Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0);
844
845/**
846 * @type {Long}
847 * @api private
848 */
8491Long.TWO_PWR_24_ = Long.fromInt(1 << 24);
850
851/**
852 * Expose.
853 */
8541exports.Long = Long;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js

50%
4
2
2
LineHitsSource
1/**
2 * A class representation of the BSON MaxKey type.
3 *
4 * @class Represents the BSON MaxKey type.
5 * @return {MaxKey}
6 */
71function MaxKey() {
80 if(!(this instanceof MaxKey)) return new MaxKey();
9
100 this._bsontype = 'MaxKey';
11}
12
131exports.MaxKey = MaxKey;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js

50%
4
2
2
LineHitsSource
1/**
2 * A class representation of the BSON MinKey type.
3 *
4 * @class Represents the BSON MinKey type.
5 * @return {MinKey}
6 */
71function MinKey() {
80 if(!(this instanceof MinKey)) return new MinKey();
9
100 this._bsontype = 'MinKey';
11}
12
131exports.MinKey = MinKey;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js

27%
76
21
55
LineHitsSource
1/**
2 * Module dependencies.
3 */
41var BinaryParser = require('./binary_parser').BinaryParser;
5
6/**
7 * Machine id.
8 *
9 * Create a random 3-byte value (i.e. unique for this
10 * process). Other drivers use a md5 of the machine id here, but
11 * that would mean an asyc call to gethostname, so we don't bother.
12 */
131var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10);
14
15// Regular expression that checks for hex value
161var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");
17
18/**
19* Create a new ObjectID instance
20*
21* @class Represents the BSON ObjectID type
22* @param {String|Number} id Can be a 24 byte hex string, 12 byte binary string or a Number.
23* @return {Object} instance of ObjectID.
24*/
251var ObjectID = function ObjectID(id) {
260 if(!(this instanceof ObjectID)) return new ObjectID(id);
27
280 this._bsontype = 'ObjectID';
290 var __id = null;
30
31 // Throw an error if it's not a valid setup
320 if(id != null && 'number' != typeof id && (id.length != 12 && id.length != 24))
330 throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters");
34
35 // Generate id based on the input
360 if(id == null || typeof id == 'number') {
37 // convert to 12 byte binary string
380 this.id = this.generate(id);
390 } else if(id != null && id.length === 12) {
40 // assume 12 byte string
410 this.id = id;
420 } else if(checkForHexRegExp.test(id)) {
430 return ObjectID.createFromHexString(id);
44 } else {
450 throw new Error("Value passed in is not a valid 24 character hex string");
46 }
47
480 if(ObjectID.cacheHexString) this.__id = this.toHexString();
49};
50
51// Allow usage of ObjectId aswell as ObjectID
521var ObjectId = ObjectID;
53
54/**
55* Return the ObjectID id as a 24 byte hex string representation
56*
57* @return {String} return the 24 byte hex string representation.
58* @api public
59*/
601ObjectID.prototype.toHexString = function() {
610 if(ObjectID.cacheHexString && this.__id) return this.__id;
62
630 var hexString = ''
64 , number
65 , value;
66
670 for (var index = 0, len = this.id.length; index < len; index++) {
680 value = BinaryParser.toByte(this.id[index]);
690 number = value <= 15
70 ? '0' + value.toString(16)
71 : value.toString(16);
720 hexString = hexString + number;
73 }
74
750 if(ObjectID.cacheHexString) this.__id = hexString;
760 return hexString;
77};
78
79/**
80* Update the ObjectID index used in generating new ObjectID's on the driver
81*
82* @return {Number} returns next index value.
83* @api private
84*/
851ObjectID.prototype.get_inc = function() {
860 return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF;
87};
88
89/**
90* Update the ObjectID index used in generating new ObjectID's on the driver
91*
92* @return {Number} returns next index value.
93* @api private
94*/
951ObjectID.prototype.getInc = function() {
960 return this.get_inc();
97};
98
99/**
100* Generate a 12 byte id string used in ObjectID's
101*
102* @param {Number} [time] optional parameter allowing to pass in a second based timestamp.
103* @return {String} return the 12 byte id binary string.
104* @api private
105*/
1061ObjectID.prototype.generate = function(time) {
1070 if ('number' != typeof time) {
1080 time = parseInt(Date.now()/1000,10);
109 }
110
1110 var time4Bytes = BinaryParser.encodeInt(time, 32, true, true);
112 /* for time-based ObjectID the bytes following the time will be zeroed */
1130 var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false);
1140 var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid);
1150 var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true);
116
1170 return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes;
118};
119
120/**
121* Converts the id into a 24 byte hex string for printing
122*
123* @return {String} return the 24 byte hex string representation.
124* @api private
125*/
1261ObjectID.prototype.toString = function() {
1270 return this.toHexString();
128};
129
130/**
131* Converts to a string representation of this Id.
132*
133* @return {String} return the 24 byte hex string representation.
134* @api private
135*/
1361ObjectID.prototype.inspect = ObjectID.prototype.toString;
137
138/**
139* Converts to its JSON representation.
140*
141* @return {String} return the 24 byte hex string representation.
142* @api private
143*/
1441ObjectID.prototype.toJSON = function() {
1450 return this.toHexString();
146};
147
148/**
149* Compares the equality of this ObjectID with `otherID`.
150*
151* @param {Object} otherID ObjectID instance to compare against.
152* @return {Bool} the result of comparing two ObjectID's
153* @api public
154*/
1551ObjectID.prototype.equals = function equals (otherID) {
1560 var id = (otherID instanceof ObjectID || otherID.toHexString)
157 ? otherID.id
158 : ObjectID.createFromHexString(otherID).id;
159
1600 return this.id === id;
161}
162
163/**
164* Returns the generation date (accurate up to the second) that this ID was generated.
165*
166* @return {Date} the generation date
167* @api public
168*/
1691ObjectID.prototype.getTimestamp = function() {
1700 var timestamp = new Date();
1710 timestamp.setTime(Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)) * 1000);
1720 return timestamp;
173}
174
175/**
176* @ignore
177* @api private
178*/
1791ObjectID.index = parseInt(Math.random() * 0xFFFFFF, 10);
180
1811ObjectID.createPk = function createPk () {
1820 return new ObjectID();
183};
184
185/**
186* Creates an ObjectID from a second based number, with the rest of the ObjectID zeroed out. Used for comparisons or sorting the ObjectID.
187*
188* @param {Number} time an integer number representing a number of seconds.
189* @return {ObjectID} return the created ObjectID
190* @api public
191*/
1921ObjectID.createFromTime = function createFromTime (time) {
1930 var id = BinaryParser.encodeInt(time, 32, true, true) +
194 BinaryParser.encodeInt(0, 64, true, true);
1950 return new ObjectID(id);
196};
197
198/**
199* Creates an ObjectID from a hex string representation of an ObjectID.
200*
201* @param {String} hexString create a ObjectID from a passed in 24 byte hexstring.
202* @return {ObjectID} return the created ObjectID
203* @api public
204*/
2051ObjectID.createFromHexString = function createFromHexString (hexString) {
206 // Throw an error if it's not a valid setup
2070 if(typeof hexString === 'undefined' || hexString != null && hexString.length != 24)
2080 throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters");
209
2100 var len = hexString.length;
211
2120 if(len > 12*2) {
2130 throw new Error('Id cannot be longer than 12 bytes');
214 }
215
2160 var result = ''
217 , string
218 , number;
219
2200 for (var index = 0; index < len; index += 2) {
2210 string = hexString.substr(index, 2);
2220 number = parseInt(string, 16);
2230 result += BinaryParser.fromByte(number);
224 }
225
2260 return new ObjectID(result, hexString);
227};
228
229/**
230* @ignore
231*/
2321Object.defineProperty(ObjectID.prototype, "generationTime", {
233 enumerable: true
234 , get: function () {
2350 return Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true));
236 }
237 , set: function (value) {
2380 var value = BinaryParser.encodeInt(value, 32, true, true);
2390 this.id = value + this.id.substr(4);
240 // delete this.__id;
2410 this.toHexString();
242 }
243});
244
245/**
246 * Expose.
247 */
2481exports.ObjectID = ObjectID;
2491exports.ObjectId = ObjectID;
250

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js

46%
13
6
7
LineHitsSource
1/**
2 * A class representation of the BSON Symbol type.
3 *
4 * @class Represents the BSON Symbol type.
5 * @param {String} value the string representing the symbol.
6 * @return {Symbol}
7 */
81function Symbol(value) {
90 if(!(this instanceof Symbol)) return new Symbol(value);
100 this._bsontype = 'Symbol';
110 this.value = value;
12}
13
14/**
15 * Access the wrapped string value.
16 *
17 * @return {String} returns the wrapped string.
18 * @api public
19 */
201Symbol.prototype.valueOf = function() {
210 return this.value;
22};
23
24/**
25 * @ignore
26 * @api private
27 */
281Symbol.prototype.toString = function() {
290 return this.value;
30}
31
32/**
33 * @ignore
34 * @api private
35 */
361Symbol.prototype.inspect = function() {
370 return this.value;
38}
39
40/**
41 * @ignore
42 * @api private
43 */
441Symbol.prototype.toJSON = function() {
450 return this.value;
46}
47
481exports.Symbol = Symbol;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js

21%
296
63
233
LineHitsSource
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// Copyright 2009 Google Inc. All Rights Reserved
14
15/**
16 * Defines a Timestamp class for representing a 64-bit two's-complement
17 * integer value, which faithfully simulates the behavior of a Java "Timestamp". This
18 * implementation is derived from TimestampLib in GWT.
19 *
20 * Constructs a 64-bit two's-complement integer, given its low and high 32-bit
21 * values as *signed* integers. See the from* functions below for more
22 * convenient ways of constructing Timestamps.
23 *
24 * The internal representation of a Timestamp is the two given signed, 32-bit values.
25 * We use 32-bit pieces because these are the size of integers on which
26 * Javascript performs bit-operations. For operations like addition and
27 * multiplication, we split each number into 16-bit pieces, which can easily be
28 * multiplied within Javascript's floating-point representation without overflow
29 * or change in sign.
30 *
31 * In the algorithms below, we frequently reduce the negative case to the
32 * positive case by negating the input(s) and then post-processing the result.
33 * Note that we must ALWAYS check specially whether those values are MIN_VALUE
34 * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
35 * a positive number, it overflows back into a negative). Not handling this
36 * case would often result in infinite recursion.
37 *
38 * @class Represents the BSON Timestamp type.
39 * @param {Number} low the low (signed) 32 bits of the Timestamp.
40 * @param {Number} high the high (signed) 32 bits of the Timestamp.
41 */
421function Timestamp(low, high) {
436 if(!(this instanceof Timestamp)) return new Timestamp(low, high);
446 this._bsontype = 'Timestamp';
45 /**
46 * @type {number}
47 * @api private
48 */
496 this.low_ = low | 0; // force into 32 signed bits.
50
51 /**
52 * @type {number}
53 * @api private
54 */
556 this.high_ = high | 0; // force into 32 signed bits.
56};
57
58/**
59 * Return the int value.
60 *
61 * @return {Number} the value, assuming it is a 32-bit integer.
62 * @api public
63 */
641Timestamp.prototype.toInt = function() {
650 return this.low_;
66};
67
68/**
69 * Return the Number value.
70 *
71 * @return {Number} the closest floating-point representation to this value.
72 * @api public
73 */
741Timestamp.prototype.toNumber = function() {
750 return this.high_ * Timestamp.TWO_PWR_32_DBL_ +
76 this.getLowBitsUnsigned();
77};
78
79/**
80 * Return the JSON value.
81 *
82 * @return {String} the JSON representation.
83 * @api public
84 */
851Timestamp.prototype.toJSON = function() {
860 return this.toString();
87}
88
89/**
90 * Return the String value.
91 *
92 * @param {Number} [opt_radix] the radix in which the text should be written.
93 * @return {String} the textual representation of this value.
94 * @api public
95 */
961Timestamp.prototype.toString = function(opt_radix) {
970 var radix = opt_radix || 10;
980 if (radix < 2 || 36 < radix) {
990 throw Error('radix out of range: ' + radix);
100 }
101
1020 if (this.isZero()) {
1030 return '0';
104 }
105
1060 if (this.isNegative()) {
1070 if (this.equals(Timestamp.MIN_VALUE)) {
108 // We need to change the Timestamp value before it can be negated, so we remove
109 // the bottom-most digit in this base and then recurse to do the rest.
1100 var radixTimestamp = Timestamp.fromNumber(radix);
1110 var div = this.div(radixTimestamp);
1120 var rem = div.multiply(radixTimestamp).subtract(this);
1130 return div.toString(radix) + rem.toInt().toString(radix);
114 } else {
1150 return '-' + this.negate().toString(radix);
116 }
117 }
118
119 // Do several (6) digits each time through the loop, so as to
120 // minimize the calls to the very expensive emulated div.
1210 var radixToPower = Timestamp.fromNumber(Math.pow(radix, 6));
122
1230 var rem = this;
1240 var result = '';
1250 while (true) {
1260 var remDiv = rem.div(radixToPower);
1270 var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
1280 var digits = intval.toString(radix);
129
1300 rem = remDiv;
1310 if (rem.isZero()) {
1320 return digits + result;
133 } else {
1340 while (digits.length < 6) {
1350 digits = '0' + digits;
136 }
1370 result = '' + digits + result;
138 }
139 }
140};
141
142/**
143 * Return the high 32-bits value.
144 *
145 * @return {Number} the high 32-bits as a signed value.
146 * @api public
147 */
1481Timestamp.prototype.getHighBits = function() {
1490 return this.high_;
150};
151
152/**
153 * Return the low 32-bits value.
154 *
155 * @return {Number} the low 32-bits as a signed value.
156 * @api public
157 */
1581Timestamp.prototype.getLowBits = function() {
1590 return this.low_;
160};
161
162/**
163 * Return the low unsigned 32-bits value.
164 *
165 * @return {Number} the low 32-bits as an unsigned value.
166 * @api public
167 */
1681Timestamp.prototype.getLowBitsUnsigned = function() {
1690 return (this.low_ >= 0) ?
170 this.low_ : Timestamp.TWO_PWR_32_DBL_ + this.low_;
171};
172
173/**
174 * Returns the number of bits needed to represent the absolute value of this Timestamp.
175 *
176 * @return {Number} Returns the number of bits needed to represent the absolute value of this Timestamp.
177 * @api public
178 */
1791Timestamp.prototype.getNumBitsAbs = function() {
1800 if (this.isNegative()) {
1810 if (this.equals(Timestamp.MIN_VALUE)) {
1820 return 64;
183 } else {
1840 return this.negate().getNumBitsAbs();
185 }
186 } else {
1870 var val = this.high_ != 0 ? this.high_ : this.low_;
1880 for (var bit = 31; bit > 0; bit--) {
1890 if ((val & (1 << bit)) != 0) {
1900 break;
191 }
192 }
1930 return this.high_ != 0 ? bit + 33 : bit + 1;
194 }
195};
196
197/**
198 * Return whether this value is zero.
199 *
200 * @return {Boolean} whether this value is zero.
201 * @api public
202 */
2031Timestamp.prototype.isZero = function() {
2040 return this.high_ == 0 && this.low_ == 0;
205};
206
207/**
208 * Return whether this value is negative.
209 *
210 * @return {Boolean} whether this value is negative.
211 * @api public
212 */
2131Timestamp.prototype.isNegative = function() {
2140 return this.high_ < 0;
215};
216
217/**
218 * Return whether this value is odd.
219 *
220 * @return {Boolean} whether this value is odd.
221 * @api public
222 */
2231Timestamp.prototype.isOdd = function() {
2240 return (this.low_ & 1) == 1;
225};
226
227/**
228 * Return whether this Timestamp equals the other
229 *
230 * @param {Timestamp} other Timestamp to compare against.
231 * @return {Boolean} whether this Timestamp equals the other
232 * @api public
233 */
2341Timestamp.prototype.equals = function(other) {
2350 return (this.high_ == other.high_) && (this.low_ == other.low_);
236};
237
238/**
239 * Return whether this Timestamp does not equal the other.
240 *
241 * @param {Timestamp} other Timestamp to compare against.
242 * @return {Boolean} whether this Timestamp does not equal the other.
243 * @api public
244 */
2451Timestamp.prototype.notEquals = function(other) {
2460 return (this.high_ != other.high_) || (this.low_ != other.low_);
247};
248
249/**
250 * Return whether this Timestamp is less than the other.
251 *
252 * @param {Timestamp} other Timestamp to compare against.
253 * @return {Boolean} whether this Timestamp is less than the other.
254 * @api public
255 */
2561Timestamp.prototype.lessThan = function(other) {
2570 return this.compare(other) < 0;
258};
259
260/**
261 * Return whether this Timestamp is less than or equal to the other.
262 *
263 * @param {Timestamp} other Timestamp to compare against.
264 * @return {Boolean} whether this Timestamp is less than or equal to the other.
265 * @api public
266 */
2671Timestamp.prototype.lessThanOrEqual = function(other) {
2680 return this.compare(other) <= 0;
269};
270
271/**
272 * Return whether this Timestamp is greater than the other.
273 *
274 * @param {Timestamp} other Timestamp to compare against.
275 * @return {Boolean} whether this Timestamp is greater than the other.
276 * @api public
277 */
2781Timestamp.prototype.greaterThan = function(other) {
2790 return this.compare(other) > 0;
280};
281
282/**
283 * Return whether this Timestamp is greater than or equal to the other.
284 *
285 * @param {Timestamp} other Timestamp to compare against.
286 * @return {Boolean} whether this Timestamp is greater than or equal to the other.
287 * @api public
288 */
2891Timestamp.prototype.greaterThanOrEqual = function(other) {
2900 return this.compare(other) >= 0;
291};
292
293/**
294 * Compares this Timestamp with the given one.
295 *
296 * @param {Timestamp} other Timestamp to compare against.
297 * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater.
298 * @api public
299 */
3001Timestamp.prototype.compare = function(other) {
3010 if (this.equals(other)) {
3020 return 0;
303 }
304
3050 var thisNeg = this.isNegative();
3060 var otherNeg = other.isNegative();
3070 if (thisNeg && !otherNeg) {
3080 return -1;
309 }
3100 if (!thisNeg && otherNeg) {
3110 return 1;
312 }
313
314 // at this point, the signs are the same, so subtraction will not overflow
3150 if (this.subtract(other).isNegative()) {
3160 return -1;
317 } else {
3180 return 1;
319 }
320};
321
322/**
323 * The negation of this value.
324 *
325 * @return {Timestamp} the negation of this value.
326 * @api public
327 */
3281Timestamp.prototype.negate = function() {
3290 if (this.equals(Timestamp.MIN_VALUE)) {
3300 return Timestamp.MIN_VALUE;
331 } else {
3320 return this.not().add(Timestamp.ONE);
333 }
334};
335
336/**
337 * Returns the sum of this and the given Timestamp.
338 *
339 * @param {Timestamp} other Timestamp to add to this one.
340 * @return {Timestamp} the sum of this and the given Timestamp.
341 * @api public
342 */
3431Timestamp.prototype.add = function(other) {
344 // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
345
3460 var a48 = this.high_ >>> 16;
3470 var a32 = this.high_ & 0xFFFF;
3480 var a16 = this.low_ >>> 16;
3490 var a00 = this.low_ & 0xFFFF;
350
3510 var b48 = other.high_ >>> 16;
3520 var b32 = other.high_ & 0xFFFF;
3530 var b16 = other.low_ >>> 16;
3540 var b00 = other.low_ & 0xFFFF;
355
3560 var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
3570 c00 += a00 + b00;
3580 c16 += c00 >>> 16;
3590 c00 &= 0xFFFF;
3600 c16 += a16 + b16;
3610 c32 += c16 >>> 16;
3620 c16 &= 0xFFFF;
3630 c32 += a32 + b32;
3640 c48 += c32 >>> 16;
3650 c32 &= 0xFFFF;
3660 c48 += a48 + b48;
3670 c48 &= 0xFFFF;
3680 return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
369};
370
371/**
372 * Returns the difference of this and the given Timestamp.
373 *
374 * @param {Timestamp} other Timestamp to subtract from this.
375 * @return {Timestamp} the difference of this and the given Timestamp.
376 * @api public
377 */
3781Timestamp.prototype.subtract = function(other) {
3790 return this.add(other.negate());
380};
381
382/**
383 * Returns the product of this and the given Timestamp.
384 *
385 * @param {Timestamp} other Timestamp to multiply with this.
386 * @return {Timestamp} the product of this and the other.
387 * @api public
388 */
3891Timestamp.prototype.multiply = function(other) {
3900 if (this.isZero()) {
3910 return Timestamp.ZERO;
3920 } else if (other.isZero()) {
3930 return Timestamp.ZERO;
394 }
395
3960 if (this.equals(Timestamp.MIN_VALUE)) {
3970 return other.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO;
3980 } else if (other.equals(Timestamp.MIN_VALUE)) {
3990 return this.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO;
400 }
401
4020 if (this.isNegative()) {
4030 if (other.isNegative()) {
4040 return this.negate().multiply(other.negate());
405 } else {
4060 return this.negate().multiply(other).negate();
407 }
4080 } else if (other.isNegative()) {
4090 return this.multiply(other.negate()).negate();
410 }
411
412 // If both Timestamps are small, use float multiplication
4130 if (this.lessThan(Timestamp.TWO_PWR_24_) &&
414 other.lessThan(Timestamp.TWO_PWR_24_)) {
4150 return Timestamp.fromNumber(this.toNumber() * other.toNumber());
416 }
417
418 // Divide each Timestamp into 4 chunks of 16 bits, and then add up 4x4 products.
419 // We can skip products that would overflow.
420
4210 var a48 = this.high_ >>> 16;
4220 var a32 = this.high_ & 0xFFFF;
4230 var a16 = this.low_ >>> 16;
4240 var a00 = this.low_ & 0xFFFF;
425
4260 var b48 = other.high_ >>> 16;
4270 var b32 = other.high_ & 0xFFFF;
4280 var b16 = other.low_ >>> 16;
4290 var b00 = other.low_ & 0xFFFF;
430
4310 var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
4320 c00 += a00 * b00;
4330 c16 += c00 >>> 16;
4340 c00 &= 0xFFFF;
4350 c16 += a16 * b00;
4360 c32 += c16 >>> 16;
4370 c16 &= 0xFFFF;
4380 c16 += a00 * b16;
4390 c32 += c16 >>> 16;
4400 c16 &= 0xFFFF;
4410 c32 += a32 * b00;
4420 c48 += c32 >>> 16;
4430 c32 &= 0xFFFF;
4440 c32 += a16 * b16;
4450 c48 += c32 >>> 16;
4460 c32 &= 0xFFFF;
4470 c32 += a00 * b32;
4480 c48 += c32 >>> 16;
4490 c32 &= 0xFFFF;
4500 c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
4510 c48 &= 0xFFFF;
4520 return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
453};
454
455/**
456 * Returns this Timestamp divided by the given one.
457 *
458 * @param {Timestamp} other Timestamp by which to divide.
459 * @return {Timestamp} this Timestamp divided by the given one.
460 * @api public
461 */
4621Timestamp.prototype.div = function(other) {
4630 if (other.isZero()) {
4640 throw Error('division by zero');
4650 } else if (this.isZero()) {
4660 return Timestamp.ZERO;
467 }
468
4690 if (this.equals(Timestamp.MIN_VALUE)) {
4700 if (other.equals(Timestamp.ONE) ||
471 other.equals(Timestamp.NEG_ONE)) {
4720 return Timestamp.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
4730 } else if (other.equals(Timestamp.MIN_VALUE)) {
4740 return Timestamp.ONE;
475 } else {
476 // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
4770 var halfThis = this.shiftRight(1);
4780 var approx = halfThis.div(other).shiftLeft(1);
4790 if (approx.equals(Timestamp.ZERO)) {
4800 return other.isNegative() ? Timestamp.ONE : Timestamp.NEG_ONE;
481 } else {
4820 var rem = this.subtract(other.multiply(approx));
4830 var result = approx.add(rem.div(other));
4840 return result;
485 }
486 }
4870 } else if (other.equals(Timestamp.MIN_VALUE)) {
4880 return Timestamp.ZERO;
489 }
490
4910 if (this.isNegative()) {
4920 if (other.isNegative()) {
4930 return this.negate().div(other.negate());
494 } else {
4950 return this.negate().div(other).negate();
496 }
4970 } else if (other.isNegative()) {
4980 return this.div(other.negate()).negate();
499 }
500
501 // Repeat the following until the remainder is less than other: find a
502 // floating-point that approximates remainder / other *from below*, add this
503 // into the result, and subtract it from the remainder. It is critical that
504 // the approximate value is less than or equal to the real value so that the
505 // remainder never becomes negative.
5060 var res = Timestamp.ZERO;
5070 var rem = this;
5080 while (rem.greaterThanOrEqual(other)) {
509 // Approximate the result of division. This may be a little greater or
510 // smaller than the actual value.
5110 var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
512
513 // We will tweak the approximate result by changing it in the 48-th digit or
514 // the smallest non-fractional digit, whichever is larger.
5150 var log2 = Math.ceil(Math.log(approx) / Math.LN2);
5160 var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
517
518 // Decrease the approximation until it is smaller than the remainder. Note
519 // that if it is too large, the product overflows and is negative.
5200 var approxRes = Timestamp.fromNumber(approx);
5210 var approxRem = approxRes.multiply(other);
5220 while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
5230 approx -= delta;
5240 approxRes = Timestamp.fromNumber(approx);
5250 approxRem = approxRes.multiply(other);
526 }
527
528 // We know the answer can't be zero... and actually, zero would cause
529 // infinite recursion since we would make no progress.
5300 if (approxRes.isZero()) {
5310 approxRes = Timestamp.ONE;
532 }
533
5340 res = res.add(approxRes);
5350 rem = rem.subtract(approxRem);
536 }
5370 return res;
538};
539
540/**
541 * Returns this Timestamp modulo the given one.
542 *
543 * @param {Timestamp} other Timestamp by which to mod.
544 * @return {Timestamp} this Timestamp modulo the given one.
545 * @api public
546 */
5471Timestamp.prototype.modulo = function(other) {
5480 return this.subtract(this.div(other).multiply(other));
549};
550
551/**
552 * The bitwise-NOT of this value.
553 *
554 * @return {Timestamp} the bitwise-NOT of this value.
555 * @api public
556 */
5571Timestamp.prototype.not = function() {
5580 return Timestamp.fromBits(~this.low_, ~this.high_);
559};
560
561/**
562 * Returns the bitwise-AND of this Timestamp and the given one.
563 *
564 * @param {Timestamp} other the Timestamp with which to AND.
565 * @return {Timestamp} the bitwise-AND of this and the other.
566 * @api public
567 */
5681Timestamp.prototype.and = function(other) {
5690 return Timestamp.fromBits(this.low_ & other.low_, this.high_ & other.high_);
570};
571
572/**
573 * Returns the bitwise-OR of this Timestamp and the given one.
574 *
575 * @param {Timestamp} other the Timestamp with which to OR.
576 * @return {Timestamp} the bitwise-OR of this and the other.
577 * @api public
578 */
5791Timestamp.prototype.or = function(other) {
5800 return Timestamp.fromBits(this.low_ | other.low_, this.high_ | other.high_);
581};
582
583/**
584 * Returns the bitwise-XOR of this Timestamp and the given one.
585 *
586 * @param {Timestamp} other the Timestamp with which to XOR.
587 * @return {Timestamp} the bitwise-XOR of this and the other.
588 * @api public
589 */
5901Timestamp.prototype.xor = function(other) {
5910 return Timestamp.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_);
592};
593
594/**
595 * Returns this Timestamp with bits shifted to the left by the given amount.
596 *
597 * @param {Number} numBits the number of bits by which to shift.
598 * @return {Timestamp} this shifted to the left by the given amount.
599 * @api public
600 */
6011Timestamp.prototype.shiftLeft = function(numBits) {
6020 numBits &= 63;
6030 if (numBits == 0) {
6040 return this;
605 } else {
6060 var low = this.low_;
6070 if (numBits < 32) {
6080 var high = this.high_;
6090 return Timestamp.fromBits(
610 low << numBits,
611 (high << numBits) | (low >>> (32 - numBits)));
612 } else {
6130 return Timestamp.fromBits(0, low << (numBits - 32));
614 }
615 }
616};
617
618/**
619 * Returns this Timestamp with bits shifted to the right by the given amount.
620 *
621 * @param {Number} numBits the number of bits by which to shift.
622 * @return {Timestamp} this shifted to the right by the given amount.
623 * @api public
624 */
6251Timestamp.prototype.shiftRight = function(numBits) {
6260 numBits &= 63;
6270 if (numBits == 0) {
6280 return this;
629 } else {
6300 var high = this.high_;
6310 if (numBits < 32) {
6320 var low = this.low_;
6330 return Timestamp.fromBits(
634 (low >>> numBits) | (high << (32 - numBits)),
635 high >> numBits);
636 } else {
6370 return Timestamp.fromBits(
638 high >> (numBits - 32),
639 high >= 0 ? 0 : -1);
640 }
641 }
642};
643
644/**
645 * Returns this Timestamp with bits shifted to the right by the given amount, with the new top bits matching the current sign bit.
646 *
647 * @param {Number} numBits the number of bits by which to shift.
648 * @return {Timestamp} this shifted to the right by the given amount, with zeros placed into the new leading bits.
649 * @api public
650 */
6511Timestamp.prototype.shiftRightUnsigned = function(numBits) {
6520 numBits &= 63;
6530 if (numBits == 0) {
6540 return this;
655 } else {
6560 var high = this.high_;
6570 if (numBits < 32) {
6580 var low = this.low_;
6590 return Timestamp.fromBits(
660 (low >>> numBits) | (high << (32 - numBits)),
661 high >>> numBits);
6620 } else if (numBits == 32) {
6630 return Timestamp.fromBits(high, 0);
664 } else {
6650 return Timestamp.fromBits(high >>> (numBits - 32), 0);
666 }
667 }
668};
669
670/**
671 * Returns a Timestamp representing the given (32-bit) integer value.
672 *
673 * @param {Number} value the 32-bit integer in question.
674 * @return {Timestamp} the corresponding Timestamp value.
675 * @api public
676 */
6771Timestamp.fromInt = function(value) {
6784 if (-128 <= value && value < 128) {
6793 var cachedObj = Timestamp.INT_CACHE_[value];
6803 if (cachedObj) {
6810 return cachedObj;
682 }
683 }
684
6854 var obj = new Timestamp(value | 0, value < 0 ? -1 : 0);
6864 if (-128 <= value && value < 128) {
6873 Timestamp.INT_CACHE_[value] = obj;
688 }
6894 return obj;
690};
691
692/**
693 * Returns a Timestamp representing the given value, provided that it is a finite number. Otherwise, zero is returned.
694 *
695 * @param {Number} value the number in question.
696 * @return {Timestamp} the corresponding Timestamp value.
697 * @api public
698 */
6991Timestamp.fromNumber = function(value) {
7000 if (isNaN(value) || !isFinite(value)) {
7010 return Timestamp.ZERO;
7020 } else if (value <= -Timestamp.TWO_PWR_63_DBL_) {
7030 return Timestamp.MIN_VALUE;
7040 } else if (value + 1 >= Timestamp.TWO_PWR_63_DBL_) {
7050 return Timestamp.MAX_VALUE;
7060 } else if (value < 0) {
7070 return Timestamp.fromNumber(-value).negate();
708 } else {
7090 return new Timestamp(
710 (value % Timestamp.TWO_PWR_32_DBL_) | 0,
711 (value / Timestamp.TWO_PWR_32_DBL_) | 0);
712 }
713};
714
715/**
716 * Returns a Timestamp representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits.
717 *
718 * @param {Number} lowBits the low 32-bits.
719 * @param {Number} highBits the high 32-bits.
720 * @return {Timestamp} the corresponding Timestamp value.
721 * @api public
722 */
7231Timestamp.fromBits = function(lowBits, highBits) {
7242 return new Timestamp(lowBits, highBits);
725};
726
727/**
728 * Returns a Timestamp representation of the given string, written using the given radix.
729 *
730 * @param {String} str the textual representation of the Timestamp.
731 * @param {Number} opt_radix the radix in which the text is written.
732 * @return {Timestamp} the corresponding Timestamp value.
733 * @api public
734 */
7351Timestamp.fromString = function(str, opt_radix) {
7360 if (str.length == 0) {
7370 throw Error('number format error: empty string');
738 }
739
7400 var radix = opt_radix || 10;
7410 if (radix < 2 || 36 < radix) {
7420 throw Error('radix out of range: ' + radix);
743 }
744
7450 if (str.charAt(0) == '-') {
7460 return Timestamp.fromString(str.substring(1), radix).negate();
7470 } else if (str.indexOf('-') >= 0) {
7480 throw Error('number format error: interior "-" character: ' + str);
749 }
750
751 // Do several (8) digits each time through the loop, so as to
752 // minimize the calls to the very expensive emulated div.
7530 var radixToPower = Timestamp.fromNumber(Math.pow(radix, 8));
754
7550 var result = Timestamp.ZERO;
7560 for (var i = 0; i < str.length; i += 8) {
7570 var size = Math.min(8, str.length - i);
7580 var value = parseInt(str.substring(i, i + size), radix);
7590 if (size < 8) {
7600 var power = Timestamp.fromNumber(Math.pow(radix, size));
7610 result = result.multiply(power).add(Timestamp.fromNumber(value));
762 } else {
7630 result = result.multiply(radixToPower);
7640 result = result.add(Timestamp.fromNumber(value));
765 }
766 }
7670 return result;
768};
769
770// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
771// from* methods on which they depend.
772
773
774/**
775 * A cache of the Timestamp representations of small integer values.
776 * @type {Object}
777 * @api private
778 */
7791Timestamp.INT_CACHE_ = {};
780
781// NOTE: the compiler should inline these constant values below and then remove
782// these variables, so there should be no runtime penalty for these.
783
784/**
785 * Number used repeated below in calculations. This must appear before the
786 * first call to any from* function below.
787 * @type {number}
788 * @api private
789 */
7901Timestamp.TWO_PWR_16_DBL_ = 1 << 16;
791
792/**
793 * @type {number}
794 * @api private
795 */
7961Timestamp.TWO_PWR_24_DBL_ = 1 << 24;
797
798/**
799 * @type {number}
800 * @api private
801 */
8021Timestamp.TWO_PWR_32_DBL_ = Timestamp.TWO_PWR_16_DBL_ * Timestamp.TWO_PWR_16_DBL_;
803
804/**
805 * @type {number}
806 * @api private
807 */
8081Timestamp.TWO_PWR_31_DBL_ = Timestamp.TWO_PWR_32_DBL_ / 2;
809
810/**
811 * @type {number}
812 * @api private
813 */
8141Timestamp.TWO_PWR_48_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_16_DBL_;
815
816/**
817 * @type {number}
818 * @api private
819 */
8201Timestamp.TWO_PWR_64_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_32_DBL_;
821
822/**
823 * @type {number}
824 * @api private
825 */
8261Timestamp.TWO_PWR_63_DBL_ = Timestamp.TWO_PWR_64_DBL_ / 2;
827
828/** @type {Timestamp} */
8291Timestamp.ZERO = Timestamp.fromInt(0);
830
831/** @type {Timestamp} */
8321Timestamp.ONE = Timestamp.fromInt(1);
833
834/** @type {Timestamp} */
8351Timestamp.NEG_ONE = Timestamp.fromInt(-1);
836
837/** @type {Timestamp} */
8381Timestamp.MAX_VALUE =
839 Timestamp.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0);
840
841/** @type {Timestamp} */
8421Timestamp.MIN_VALUE = Timestamp.fromBits(0, 0x80000000 | 0);
843
844/**
845 * @type {Timestamp}
846 * @api private
847 */
8481Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24);
849
850/**
851 * Expose.
852 */
8531exports.Timestamp = Timestamp;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js

13%
132
18
114
LineHitsSource
11var format = require('util').format;
2
31var MongoAuthProcess = function(host, port, service_name) {
4 // Check what system we are on
50 if(process.platform == 'win32') {
60 this._processor = new Win32MongoProcessor(host, port, service_name);
7 } else {
80 this._processor = new UnixMongoProcessor(host, port, service_name);
9 }
10}
11
121MongoAuthProcess.prototype.init = function(username, password, callback) {
130 this._processor.init(username, password, callback);
14}
15
161MongoAuthProcess.prototype.transition = function(payload, callback) {
170 this._processor.transition(payload, callback);
18}
19
20/*******************************************************************
21 *
22 * Win32 SSIP Processor for MongoDB
23 *
24 *******************************************************************/
251var Win32MongoProcessor = function(host, port, service_name) {
260 this.host = host;
270 this.port = port
28 // SSIP classes
290 this.ssip = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/../kerberos").SSIP;
30 // Set up first transition
310 this._transition = Win32MongoProcessor.first_transition(this);
32 // Set up service name
330 service_name = service_name || "mongodb";
34 // Set up target
350 this.target = format("%s/%s", service_name, host);
36 // Number of retries
370 this.retries = 10;
38}
39
401Win32MongoProcessor.prototype.init = function(username, password, callback) {
410 var self = this;
42 // Save the values used later
430 this.username = username;
440 this.password = password;
45 // Aquire credentials
460 this.ssip.SecurityCredentials.aquire_kerberos(username, password, function(err, security_credentials) {
470 if(err) return callback(err);
48 // Save credentials
490 self.security_credentials = security_credentials;
50 // Callback with success
510 callback(null);
52 });
53}
54
551Win32MongoProcessor.prototype.transition = function(payload, callback) {
560 if(this._transition == null) return callback(new Error("Transition finished"));
570 this._transition(payload, callback);
58}
59
601Win32MongoProcessor.first_transition = function(self) {
610 return function(payload, callback) {
620 self.ssip.SecurityContext.initialize(
63 self.security_credentials,
64 self.target,
65 payload, function(err, security_context) {
660 if(err) return callback(err);
67
68 // If no context try again until we have no more retries
690 if(!security_context.hasContext) {
700 if(self.retries == 0) return callback(new Error("Failed to initialize security context"));
71 // Update the number of retries
720 self.retries = self.retries - 1;
73 // Set next transition
740 return self.transition(payload, callback);
75 }
76
77 // Set next transition
780 self._transition = Win32MongoProcessor.second_transition(self);
790 self.security_context = security_context;
80 // Return the payload
810 callback(null, security_context.payload);
82 });
83 }
84}
85
861Win32MongoProcessor.second_transition = function(self) {
870 return function(payload, callback) {
88 // Perform a step
890 self.security_context.initialize(self.target, payload, function(err, security_context) {
900 if(err) return callback(err);
91
92 // If no context try again until we have no more retries
930 if(!security_context.hasContext) {
940 if(self.retries == 0) return callback(new Error("Failed to initialize security context"));
95 // Update the number of retries
960 self.retries = self.retries - 1;
97 // Set next transition
980 self._transition = Win32MongoProcessor.first_transition(self);
99 // Retry
1000 return self.transition(payload, callback);
101 }
102
103 // Set next transition
1040 self._transition = Win32MongoProcessor.third_transition(self);
105 // Return the payload
1060 callback(null, security_context.payload);
107 });
108 }
109}
110
1111Win32MongoProcessor.third_transition = function(self) {
1120 return function(payload, callback) {
1130 var messageLength = 0;
114 // Get the raw bytes
1150 var encryptedBytes = new Buffer(payload, 'base64');
1160 var encryptedMessage = new Buffer(messageLength);
117 // Copy first byte
1180 encryptedBytes.copy(encryptedMessage, 0, 0, messageLength);
119 // Set up trailer
1200 var securityTrailerLength = encryptedBytes.length - messageLength;
1210 var securityTrailer = new Buffer(securityTrailerLength);
122 // Copy the bytes
1230 encryptedBytes.copy(securityTrailer, 0, messageLength, securityTrailerLength);
124
125 // Types used
1260 var SecurityBuffer = self.ssip.SecurityBuffer;
1270 var SecurityBufferDescriptor = self.ssip.SecurityBufferDescriptor;
128
129 // Set up security buffers
1300 var buffers = [
131 new SecurityBuffer(SecurityBuffer.DATA, encryptedBytes)
132 , new SecurityBuffer(SecurityBuffer.STREAM, securityTrailer)
133 ];
134
135 // Set up the descriptor
1360 var descriptor = new SecurityBufferDescriptor(buffers);
137
138 // Decrypt the data
1390 self.security_context.decryptMessage(descriptor, function(err, security_context) {
1400 if(err) return callback(err);
141
1420 var length = 4;
1430 if(self.username != null) {
1440 length += self.username.length;
145 }
146
1470 var bytesReceivedFromServer = new Buffer(length);
1480 bytesReceivedFromServer[0] = 0x01; // NO_PROTECTION
1490 bytesReceivedFromServer[1] = 0x00; // NO_PROTECTION
1500 bytesReceivedFromServer[2] = 0x00; // NO_PROTECTION
1510 bytesReceivedFromServer[3] = 0x00; // NO_PROTECTION
152
1530 if(self.username != null) {
1540 var authorization_id_bytes = new Buffer(self.username, 'utf8');
1550 authorization_id_bytes.copy(bytesReceivedFromServer, 4, 0);
156 }
157
1580 self.security_context.queryContextAttributes(0x00, function(err, sizes) {
1590 if(err) return callback(err);
160
1610 var buffers = [
162 new SecurityBuffer(SecurityBuffer.TOKEN, new Buffer(sizes.securityTrailer))
163 , new SecurityBuffer(SecurityBuffer.DATA, bytesReceivedFromServer)
164 , new SecurityBuffer(SecurityBuffer.PADDING, new Buffer(sizes.blockSize))
165 ]
166
1670 var descriptor = new SecurityBufferDescriptor(buffers);
168
1690 self.security_context.encryptMessage(descriptor, 0x80000001, function(err, security_context) {
1700 if(err) return callback(err);
1710 callback(null, security_context.payload);
172 });
173 });
174 });
175 }
176}
177
178/*******************************************************************
179 *
180 * UNIX MIT Kerberos processor
181 *
182 *******************************************************************/
1831var UnixMongoProcessor = function(host, port, service_name) {
1840 this.host = host;
1850 this.port = port
186 // SSIP classes
1870 this.Kerberos = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/../kerberos").Kerberos;
1880 this.kerberos = new this.Kerberos();
1890 service_name = service_name || "mongodb";
190 // Set up first transition
1910 this._transition = UnixMongoProcessor.first_transition(this);
192 // Set up target
1930 this.target = format("%s@%s", service_name, host);
194 // Number of retries
1950 this.retries = 10;
196}
197
1981UnixMongoProcessor.prototype.init = function(username, password, callback) {
1990 var self = this;
2000 this.username = username;
2010 this.password = password;
202 // Call client initiate
2030 this.kerberos.authGSSClientInit(
204 self.target
205 , this.Kerberos.GSS_C_MUTUAL_FLAG, function(err, context) {
2060 self.context = context;
207 // Return the context
2080 callback(null, context);
209 });
210}
211
2121UnixMongoProcessor.prototype.transition = function(payload, callback) {
2130 if(this._transition == null) return callback(new Error("Transition finished"));
2140 this._transition(payload, callback);
215}
216
2171UnixMongoProcessor.first_transition = function(self) {
2180 return function(payload, callback) {
2190 self.kerberos.authGSSClientStep(self.context, '', function(err, result) {
2200 if(err) return callback(err);
221 // Set up the next step
2220 self._transition = UnixMongoProcessor.second_transition(self);
223 // Return the payload
2240 callback(null, self.context.response);
225 })
226 }
227}
228
2291UnixMongoProcessor.second_transition = function(self) {
2300 return function(payload, callback) {
2310 self.kerberos.authGSSClientStep(self.context, payload, function(err, result) {
2320 if(err && self.retries == 0) return callback(err);
233 // Attempt to re-establish a context
2340 if(err) {
235 // Adjust the number of retries
2360 self.retries = self.retries - 1;
237 // Call same step again
2380 return self.transition(payload, callback);
239 }
240
241 // Set up the next step
2420 self._transition = UnixMongoProcessor.third_transition(self);
243 // Return the payload
2440 callback(null, self.context.response || '');
245 });
246 }
247}
248
2491UnixMongoProcessor.third_transition = function(self) {
2500 return function(payload, callback) {
251 // GSS Client Unwrap
2520 self.kerberos.authGSSClientUnwrap(self.context, payload, function(err, result) {
2530 if(err) return callback(err, false);
254
255 // Wrap the response
2560 self.kerberos.authGSSClientWrap(self.context, self.context.response, self.username, function(err, result) {
2570 if(err) return callback(err, false);
258 // Set up the next step
2590 self._transition = UnixMongoProcessor.fourth_transition(self);
260 // Return the payload
2610 callback(null, self.context.response);
262 });
263 });
264 }
265}
266
2671UnixMongoProcessor.fourth_transition = function(self) {
2680 return function(payload, callback) {
269 // Clean up context
2700 self.kerberos.authGSSClientClean(self.context, function(err, result) {
2710 if(err) return callback(err, false);
272 // Set the transition to null
2730 self._transition = null;
274 // Callback with valid authentication
2750 callback(null, true);
276 });
277 }
278}
279
280// Set the process
2811exports.MongoAuthProcess = MongoAuthProcess;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mockgoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js

53%
47
25
22
LineHitsSource
11var kerberos = require('../build/Release/kerberos')
2 , KerberosNative = kerberos.Kerberos;
3
41var Kerberos = function() {
50 this._native_kerberos = new KerberosNative();
6}
7
81Kerberos.prototype.authGSSClientInit = function(uri, flags, callback) {
90 return this._native_kerberos.authGSSClientInit(uri, flags, callback);
10}
11
121Kerberos.prototype.authGSSClientStep = function(context, challenge, callback) {
130 if(typeof challenge == 'function') {
140 callback = challenge;
150 challenge = '';
16 }
17
180 return this._native_kerberos.authGSSClientStep(context, challenge, callback);
19}
20
211Kerberos.prototype.authGSSClientUnwrap = function(context, challenge, callback) {
220 if(typeof challenge == 'function') {
230 callback = challenge;
240 challenge = '';
25 }
26
270 return this._native_kerberos.authGSSClientUnwrap(context, challenge, callback);
28}
29
301Kerberos.prototype.authGSSClientWrap = function(context, challenge, user_name, callback) {
310 if(typeof user_name == 'function') {
320 callback = user_name;
330 user_name = '';
34 }
35
360 return this._native_kerberos.authGSSClientWrap(context, challenge, user_name, callback);
37}
38
391Kerberos.prototype.authGSSClientClean = function(context, callback) {
400 return this._native_kerberos.authGSSClientClean(context, callback);
41}
42
431Kerberos.prototype.acquireAlternateCredentials = function(user_name, password, domain) {
440 return this._native_kerberos.acquireAlternateCredentials(user_name, password, domain);
45}
46
471Kerberos.prototype.prepareOutboundPackage = function(principal, inputdata) {
480 return this._native_kerberos.prepareOutboundPackage(principal, inputdata);
49}
50
511Kerberos.prototype.decryptMessage = function(challenge) {
520 return this._native_kerberos.decryptMessage(challenge);
53}
54
551Kerberos.prototype.encryptMessage = function(challenge) {
560 return this._native_kerberos.encryptMessage(challenge);
57}
58
591Kerberos.prototype.queryContextAttribute = function(attribute) {
600 if(typeof attribute != 'number' && attribute != 0x00) throw new Error("Attribute not supported");
610 return this._native_kerberos.queryContextAttribute(attribute);
62}
63
64// Some useful result codes
651Kerberos.AUTH_GSS_CONTINUE = 0;
661Kerberos.AUTH_GSS_COMPLETE = 1;
67
68// Some useful gss flags
691Kerberos.GSS_C_DELEG_FLAG = 1;
701Kerberos.GSS_C_MUTUAL_FLAG = 2;
711Kerberos.GSS_C_REPLAY_FLAG = 4;
721Kerberos.GSS_C_SEQUENCE_FLAG = 8;
731Kerberos.GSS_C_CONF_FLAG = 16;
741Kerberos.GSS_C_INTEG_FLAG = 32;
751Kerberos.GSS_C_ANON_FLAG = 64;
761Kerberos.GSS_C_PROT_READY_FLAG = 128;
771Kerberos.GSS_C_TRANS_FLAG = 256;
78
79// Export Kerberos class
801exports.Kerberos = Kerberos;
81
82// If we have SSPI (windows)
831if(kerberos.SecurityCredentials) {
84 // Put all SSPI classes in it's own namespace
850 exports.SSIP = {
86 SecurityCredentials: require('./win32/wrappers/security_credentials').SecurityCredentials
87 , SecurityContext: require('./win32/wrappers/security_context').SecurityContext
88 , SecurityBuffer: require('./win32/wrappers/security_buffer').SecurityBuffer
89 , SecurityBufferDescriptor: require('./win32/wrappers/security_buffer_descriptor').SecurityBufferDescriptor
90 }
91}
92

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/aggregate.js

17%
81
14
67
LineHitsSource
1/*!
2 * Module dependencies
3 */
4
51var Promise = require('./promise')
6 , util = require('util')
7 , utils = require('./utils')
8 , Query = require('./query')
9 , read = Query.prototype.read
10
11/**
12 * Aggregate constructor used for building aggregation pipelines.
13 *
14 * ####Example:
15 *
16 * new Aggregate();
17 * new Aggregate({ $project: { a: 1, b: 1 } });
18 * new Aggregate({ $project: { a: 1, b: 1 } }, { $skip: 5 });
19 * new Aggregate([{ $project: { a: 1, b: 1 } }, { $skip: 5 }]);
20 *
21 * Returned when calling Model.aggregate().
22 *
23 * ####Example:
24 *
25 * Model
26 * .aggregate({ $match: { age: { $gte: 21 }}})
27 * .unwind('tags')
28 * .exec(callback)
29 *
30 * ####Note:
31 *
32 * - The documents returned are plain javascript objects, not mongoose documents (since any shape of document can be returned).
33 * - Requires MongoDB >= 2.1
34 *
35 * @see MongoDB http://docs.mongodb.org/manual/applications/aggregation/
36 * @see driver http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate
37 * @param {Object|Array} [ops] aggregation operator(s) or operator array
38 * @api public
39 */
40
411function Aggregate () {
420 this._pipeline = [];
430 this._model = undefined;
440 this.options = undefined;
45
460 if (1 === arguments.length && util.isArray(arguments[0])) {
470 this.append.apply(this, arguments[0]);
48 } else {
490 this.append.apply(this, arguments);
50 }
51}
52
53/**
54 * Binds this aggregate to a model.
55 *
56 * @param {Model} model the model to which the aggregate is to be bound
57 * @return {Aggregate}
58 * @api private
59 */
60
611Aggregate.prototype.bind = function (model) {
620 this._model = model;
630 return this;
64}
65
66/**
67 * Appends new operators to this aggregate pipeline
68 *
69 * ####Examples:
70 *
71 * aggregate.append({ $project: { field: 1 }}, { $limit: 2 });
72 *
73 * // or pass an array
74 * var pipeline = [{ $match: { daw: 'Logic Audio X' }} ];
75 * aggregate.append(pipeline);
76 *
77 * @param {Object} ops operator(s) to append
78 * @return {Aggregate}
79 * @api public
80 */
81
821Aggregate.prototype.append = function () {
830 var args = utils.args(arguments)
84 , arg;
85
860 if (!args.every(isOperator)) {
870 throw new Error("Arguments must be aggregate pipeline operators");
88 }
89
900 this._pipeline = this._pipeline.concat(args);
91
920 return this;
93}
94
95/**
96 * Appends a new $project operator to this aggregate pipeline.
97 *
98 * Mongoose query [selection syntax](#query_Query-select) is also supported.
99 *
100 * ####Examples:
101 *
102 * // include a, include b, exclude _id
103 * aggregate.project("a b -_id");
104 *
105 * // or you may use object notation, useful when
106 * // you have keys already prefixed with a "-"
107 * aggregate.project({a: 1, b: 1, _id: 0});
108 *
109 * // reshaping documents
110 * aggregate.project({
111 * newField: '$b.nested'
112 * , plusTen: { $add: ['$val', 10]}
113 * , sub: {
114 * name: '$a'
115 * }
116 * })
117 *
118 * // etc
119 * aggregate.project({ salary_k: { $divide: [ "$salary", 1000 ] } });
120 *
121 * @param {Object|String} arg field specification
122 * @see projection http://docs.mongodb.org/manual/reference/aggregation/project/
123 * @return {Aggregate}
124 * @api public
125 */
126
1271Aggregate.prototype.project = function (arg) {
1280 var fields = {};
129
1300 if ('object' === typeof arg && !util.isArray(arg)) {
1310 Object.keys(arg).forEach(function (field) {
1320 fields[field] = arg[field];
133 });
1340 } else if (1 === arguments.length && 'string' === typeof arg) {
1350 arg.split(/\s+/).forEach(function (field) {
1360 if (!field) return;
1370 var include = '-' == field[0] ? 0 : 1;
1380 if (include === 0) field = field.substring(1);
1390 fields[field] = include;
140 });
141 } else {
1420 throw new Error("Invalid project() argument. Must be string or object");
143 }
144
1450 return this.append({ $project: fields });
146}
147
148/**
149 * Appends a new custom $group operator to this aggregate pipeline.
150 *
151 * ####Examples:
152 *
153 * aggregate.group({ _id: "$department" });
154 *
155 * @see $group http://docs.mongodb.org/manual/reference/aggregation/group/
156 * @method group
157 * @memberOf Aggregate
158 * @param {Object} arg $group operator contents
159 * @return {Aggregate}
160 * @api public
161 */
162
163/**
164 * Appends a new custom $match operator to this aggregate pipeline.
165 *
166 * ####Examples:
167 *
168 * aggregate.match({ department: { $in: [ "sales", "engineering" } } });
169 *
170 * @see $match http://docs.mongodb.org/manual/reference/aggregation/match/
171 * @method match
172 * @memberOf Aggregate
173 * @param {Object} arg $match operator contents
174 * @return {Aggregate}
175 * @api public
176 */
177
178/**
179 * Appends a new $skip operator to this aggregate pipeline.
180 *
181 * ####Examples:
182 *
183 * aggregate.skip(10);
184 *
185 * @see $skip http://docs.mongodb.org/manual/reference/aggregation/skip/
186 * @method skip
187 * @memberOf Aggregate
188 * @param {Number} num number of records to skip before next stage
189 * @return {Aggregate}
190 * @api public
191 */
192
193/**
194 * Appends a new $limit operator to this aggregate pipeline.
195 *
196 * ####Examples:
197 *
198 * aggregate.limit(10);
199 *
200 * @see $limit http://docs.mongodb.org/manual/reference/aggregation/limit/
201 * @method limit
202 * @memberOf Aggregate
203 * @param {Number} num maximum number of records to pass to the next stage
204 * @return {Aggregate}
205 * @api public
206 */
207
208/**
209 * Appends a new $geoNear operator to this aggregate pipeline.
210 *
211 * ####NOTE:
212 *
213 * **MUST** be used as the first operator in the pipeline.
214 *
215 * ####Examples:
216 *
217 * aggregate.near({
218 * near: [40.724, -73.997],
219 * distanceField: "dist.calculated", // required
220 * maxDistance: 0.008,
221 * query: { type: "public" },
222 * includeLocs: "dist.location",
223 * uniqueDocs: true,
224 * num: 5
225 * });
226 *
227 * @see $geoNear http://docs.mongodb.org/manual/reference/aggregation/geoNear/
228 * @method near
229 * @memberOf Aggregate
230 * @param {Object} parameters
231 * @return {Aggregate}
232 * @api public
233 */
234
2351Aggregate.prototype.near = function (arg) {
2360 var op = {};
2370 op.$geoNear = arg;
2380 return this.append(op);
239};
240
241/*!
242 * define methods
243 */
244
2451'group match skip limit'.split(' ').forEach(function ($operator) {
2464 Aggregate.prototype[$operator] = function (arg) {
2470 var op = {};
2480 op['$' + $operator] = arg;
2490 return this.append(op);
250 };
251});
252
253/**
254 * Appends new custom $unwind operator(s) to this aggregate pipeline.
255 *
256 * ####Examples:
257 *
258 * aggregate.unwind("tags");
259 * aggregate.unwind("a", "b", "c");
260 *
261 * @see $unwind http://docs.mongodb.org/manual/reference/aggregation/unwind/
262 * @param {String} fields the field(s) to unwind
263 * @return {Aggregate}
264 * @api public
265 */
266
2671Aggregate.prototype.unwind = function () {
2680 var args = utils.args(arguments);
269
2700 return this.append.apply(this, args.map(function (arg) {
2710 return { $unwind: '$' + arg };
272 }));
273}
274
275/**
276 * Appends a new $sort operator to this aggregate pipeline.
277 *
278 * If an object is passed, values allowed are `asc`, `desc`, `ascending`, `descending`, `1`, and `-1`.
279 *
280 * If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with `-` which will be treated as descending.
281 *
282 * ####Examples:
283 *
284 * // these are equivalent
285 * aggregate.sort({ field: 'asc', test: -1 });
286 * aggregate.sort('field -test');
287 *
288 * @see $sort http://docs.mongodb.org/manual/reference/aggregation/sort/
289 * @param {Object|String} arg
290 * @return {Query} this
291 * @api public
292 */
293
2941Aggregate.prototype.sort = function (arg) {
295 // TODO refactor to reuse the query builder logic
296
2970 var sort = {};
298
2990 if ('Object' === arg.constructor.name) {
3000 var desc = ['desc', 'descending', -1];
3010 Object.keys(arg).forEach(function (field) {
3020 sort[field] = desc.indexOf(arg[field]) === -1 ? 1 : -1;
303 });
3040 } else if (1 === arguments.length && 'string' == typeof arg) {
3050 arg.split(/\s+/).forEach(function (field) {
3060 if (!field) return;
3070 var ascend = '-' == field[0] ? -1 : 1;
3080 if (ascend === -1) field = field.substring(1);
3090 sort[field] = ascend;
310 });
311 } else {
3120 throw new TypeError('Invalid sort() argument. Must be a string or object.');
313 }
314
3150 return this.append({ $sort: sort });
316}
317
318/**
319 * Sets the readPreference option for the aggregation query.
320 *
321 * ####Example:
322 *
323 * Model.aggregate(..).read('primaryPreferred').exec(callback)
324 *
325 * @param {String} pref one of the listed preference options or their aliases
326 * @param {Array} [tags] optional tags for this query
327 * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference
328 * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences
329 */
330
3311Aggregate.prototype.read = function (pref) {
3320 if (!this.options) this.options = {};
3330 read.apply(this, arguments);
3340 return this;
335}
336
337/**
338 * Executes the aggregate pipeline on the currently bound Model.
339 *
340 * ####Example:
341 *
342 * aggregate.exec(callback);
343 *
344 * // Because a promise is returned, the `callback` is optional.
345 * var promise = aggregate.exec();
346 * promise.then(..);
347 *
348 * @see Promise #promise_Promise
349 * @param {Function} [callback]
350 * @return {Promise}
351 * @api public
352 */
353
3541Aggregate.prototype.exec = function (callback) {
3550 var promise = new Promise();
356
3570 if (callback) {
3580 promise.addBack(callback);
359 }
360
3610 if (!this._pipeline.length) {
3620 promise.error(new Error("Aggregate has empty pipeline"));
3630 return promise;
364 }
365
3660 if (!this._model) {
3670 promise.error(new Error("Aggregate not bound to any Model"));
3680 return promise;
369 }
370
3710 this._model
372 .collection
373 .aggregate(this._pipeline, this.options || {}, promise.resolve.bind(promise));
374
3750 return promise;
376}
377
378/*!
379 * Helpers
380 */
381
382/**
383 * Checks whether an object is likely a pipeline operator
384 *
385 * @param {Object} obj object to check
386 * @return {Boolean}
387 * @api private
388 */
389
3901function isOperator (obj) {
3910 var k;
392
3930 if ('object' !== typeof obj) {
3940 return false;
395 }
396
3970 k = Object.keys(obj);
398
3990 return 1 === k.length && k.some(function (key) {
4000 return '$' === key[0];
401 });
402}
403
404/*!
405 * Exports
406 */
407
4081module.exports = Aggregate;
409

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/collection.js

36%
50
18
32
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var STATES = require('./connectionstate')
7
8/**
9 * Abstract Collection constructor
10 *
11 * This is the base class that drivers inherit from and implement.
12 *
13 * @param {String} name name of the collection
14 * @param {Connection} conn A MongooseConnection instance
15 * @param {Object} opts optional collection options
16 * @api public
17 */
18
191function Collection (name, conn, opts) {
200 if (undefined === opts) opts = {};
210 if (undefined === opts.capped) opts.capped = {};
22
230 opts.bufferCommands = undefined === opts.bufferCommands
24 ? true
25 : opts.bufferCommands;
26
270 if ('number' == typeof opts.capped) {
280 opts.capped = { size: opts.capped };
29 }
30
310 this.opts = opts;
320 this.name = name;
330 this.conn = conn;
340 this.queue = [];
350 this.buffer = this.opts.bufferCommands;
36
370 if (STATES.connected == this.conn.readyState) {
380 this.onOpen();
39 }
40};
41
42/**
43 * The collection name
44 *
45 * @api public
46 * @property name
47 */
48
491Collection.prototype.name;
50
51/**
52 * The Connection instance
53 *
54 * @api public
55 * @property conn
56 */
57
581Collection.prototype.conn;
59
60/**
61 * Called when the database connects
62 *
63 * @api private
64 */
65
661Collection.prototype.onOpen = function () {
670 var self = this;
680 this.buffer = false;
690 self.doQueue();
70};
71
72/**
73 * Called when the database disconnects
74 *
75 * @api private
76 */
77
781Collection.prototype.onClose = function () {
790 if (this.opts.bufferCommands) {
800 this.buffer = true;
81 }
82};
83
84/**
85 * Queues a method for later execution when its
86 * database connection opens.
87 *
88 * @param {String} name name of the method to queue
89 * @param {Array} args arguments to pass to the method when executed
90 * @api private
91 */
92
931Collection.prototype.addQueue = function (name, args) {
940 this.queue.push([name, args]);
950 return this;
96};
97
98/**
99 * Executes all queued methods and clears the queue.
100 *
101 * @api private
102 */
103
1041Collection.prototype.doQueue = function () {
1050 for (var i = 0, l = this.queue.length; i < l; i++){
1060 this[this.queue[i][0]].apply(this, this.queue[i][1]);
107 }
1080 this.queue = [];
1090 return this;
110};
111
112/**
113 * Abstract method that drivers must implement.
114 */
115
1161Collection.prototype.ensureIndex = function(){
1170 throw new Error('Collection#ensureIndex unimplemented by driver');
118};
119
120/**
121 * Abstract method that drivers must implement.
122 */
123
1241Collection.prototype.findAndModify = function(){
1250 throw new Error('Collection#findAndModify unimplemented by driver');
126};
127
128/**
129 * Abstract method that drivers must implement.
130 */
131
1321Collection.prototype.findOne = function(){
1330 throw new Error('Collection#findOne unimplemented by driver');
134};
135
136/**
137 * Abstract method that drivers must implement.
138 */
139
1401Collection.prototype.find = function(){
1410 throw new Error('Collection#find unimplemented by driver');
142};
143
144/**
145 * Abstract method that drivers must implement.
146 */
147
1481Collection.prototype.insert = function(){
1490 throw new Error('Collection#insert unimplemented by driver');
150};
151
152/**
153 * Abstract method that drivers must implement.
154 */
155
1561Collection.prototype.save = function(){
1570 throw new Error('Collection#save unimplemented by driver');
158};
159
160/**
161 * Abstract method that drivers must implement.
162 */
163
1641Collection.prototype.update = function(){
1650 throw new Error('Collection#update unimplemented by driver');
166};
167
168/**
169 * Abstract method that drivers must implement.
170 */
171
1721Collection.prototype.getIndexes = function(){
1730 throw new Error('Collection#getIndexes unimplemented by driver');
174};
175
176/**
177 * Abstract method that drivers must implement.
178 */
179
1801Collection.prototype.mapReduce = function(){
1810 throw new Error('Collection#mapReduce unimplemented by driver');
182};
183
184/*!
185 * Module exports.
186 */
187
1881module.exports = Collection;
189

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/connection.js

29%
257
75
182
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var url = require('url')
6 , utils = require('./utils')
7 , EventEmitter = require('events').EventEmitter
8 , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'
9 , Model = require('./model')
10 , Schema = require('./schema')
11 , Collection = require(driver + '/collection')
12 , STATES = require('./connectionstate')
13 , MongooseError = require('./error')
14 , assert =require('assert')
15 , muri = require('muri')
16
17/*!
18 * Protocol prefix regexp.
19 *
20 * @api private
21 */
22
231var rgxProtocol = /^(?:.)+:\/\//;
24
25/**
26 * Connection constructor
27 *
28 * For practical reasons, a Connection equals a Db.
29 *
30 * @param {Mongoose} base a mongoose instance
31 * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
32 * @event `connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection.
33 * @event `connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios.
34 * @event `open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models.
35 * @event `disconnecting`: Emitted when `connection.close()` was executed.
36 * @event `disconnected`: Emitted after getting disconnected from the db.
37 * @event `close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models.
38 * @event `reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection.
39 * @event `error`: Emitted when an error occurs on this connection.
40 * @event `fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.
41 * @api public
42 */
43
441function Connection (base) {
451 this.base = base;
461 this.collections = {};
471 this.models = {};
481 this.replica = false;
491 this.hosts = null;
501 this.host = null;
511 this.port = null;
521 this.user = null;
531 this.pass = null;
541 this.name = null;
551 this.options = null;
561 this.otherDbs = [];
571 this._readyState = STATES.disconnected;
581 this._closeCalled = false;
591 this._hasOpened = false;
60};
61
62/*!
63 * Inherit from EventEmitter
64 */
65
661Connection.prototype.__proto__ = EventEmitter.prototype;
67
68/**
69 * Connection ready state
70 *
71 * - 0 = disconnected
72 * - 1 = connected
73 * - 2 = connecting
74 * - 3 = disconnecting
75 *
76 * Each state change emits its associated event name.
77 *
78 * ####Example
79 *
80 * conn.on('connected', callback);
81 * conn.on('disconnected', callback);
82 *
83 * @property readyState
84 * @api public
85 */
86
871Object.defineProperty(Connection.prototype, 'readyState', {
881 get: function(){ return this._readyState; }
89 , set: function (val) {
901 if (!(val in STATES)) {
910 throw new Error('Invalid connection state: ' + val);
92 }
93
941 if (this._readyState !== val) {
951 this._readyState = val;
96 // loop over the otherDbs on this connection and change their state
971 for (var i=0; i < this.otherDbs.length; i++) {
980 this.otherDbs[i].readyState = val;
99 }
100
1011 if (STATES.connected === val)
1020 this._hasOpened = true;
103
1041 this.emit(STATES[val]);
105 }
106 }
107});
108
109/**
110 * A hash of the collections associated with this connection
111 *
112 * @property collections
113 */
114
1151Connection.prototype.collections;
116
117/**
118 * The mongodb.Db instance, set when the connection is opened
119 *
120 * @property db
121 */
122
1231Connection.prototype.db;
124
125/**
126 * Opens the connection to MongoDB.
127 *
128 * `options` is a hash with the following possible properties:
129 *
130 * db - passed to the connection db instance
131 * server - passed to the connection server instance(s)
132 * replset - passed to the connection ReplSet instance
133 * user - username for authentication
134 * pass - password for authentication
135 * auth - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)
136 *
137 * ####Notes:
138 *
139 * Mongoose forces the db option `forceServerObjectId` false and cannot be overridden.
140 * Mongoose defaults the server `auto_reconnect` options to true which can be overridden.
141 * See the node-mongodb-native driver instance for options that it understands.
142 *
143 * _Options passed take precedence over options included in connection strings._
144 *
145 * @param {String} connection_string mongodb://uri or the host to which you are connecting
146 * @param {String} [database] database name
147 * @param {Number} [port] database port
148 * @param {Object} [options] options
149 * @param {Function} [callback]
150 * @see node-mongodb-native https://github.com/mongodb/node-mongodb-native
151 * @see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate
152 * @api public
153 */
154
1551Connection.prototype.open = function (host, database, port, options, callback) {
1561 var self = this
157 , parsed
158 , uri;
159
1601 if ('string' === typeof database) {
1610 switch (arguments.length) {
162 case 2:
1630 port = 27017;
164 case 3:
1650 switch (typeof port) {
166 case 'function':
1670 callback = port, port = 27017;
1680 break;
169 case 'object':
1700 options = port, port = 27017;
1710 break;
172 }
1730 break;
174 case 4:
1750 if ('function' === typeof options)
1760 callback = options, options = {};
177 }
178 } else {
1791 switch (typeof database) {
180 case 'function':
1810 callback = database, database = undefined;
1820 break;
183 case 'object':
1841 options = database;
1851 database = undefined;
1861 callback = port;
1871 break;
188 }
189
1901 if (!rgxProtocol.test(host)) {
1911 host = 'mongodb://' + host;
192 }
193
1941 try {
1951 parsed = muri(host);
196 } catch (err) {
1970 this.error(err, callback);
1980 return this;
199 }
200
2011 database = parsed.db;
2021 host = parsed.hosts[0].host || parsed.hosts[0].ipc;
2031 port = parsed.hosts[0].port || 27017;
204 }
205
2061 this.options = this.parseOptions(options, parsed && parsed.options);
207
208 // make sure we can open
2091 if (STATES.disconnected !== this.readyState) {
2100 var err = new Error('Trying to open unclosed connection.');
2110 err.state = this.readyState;
2120 this.error(err, callback);
2130 return this;
214 }
215
2161 if (!host) {
2170 this.error(new Error('Missing hostname.'), callback);
2180 return this;
219 }
220
2211 if (!database) {
2220 this.error(new Error('Missing database name.'), callback);
2230 return this;
224 }
225
226 // authentication
2271 if (options && options.user && options.pass) {
2280 this.user = options.user;
2290 this.pass = options.pass;
230
2311 } else if (parsed && parsed.auth) {
2320 this.user = parsed.auth.user;
2330 this.pass = parsed.auth.pass;
234
235 // Check hostname for user/pass
2361 } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
2370 host = host.split('@');
2380 var auth = host.shift().split(':');
2390 host = host.pop();
2400 this.user = auth[0];
2410 this.pass = auth[1];
242
243 } else {
2441 this.user = this.pass = undefined;
245 }
246
2471 this.name = database;
2481 this.host = host;
2491 this.port = port;
250
2511 this._open(callback);
2521 return this;
253};
254
255/**
256 * Opens the connection to a replica set.
257 *
258 * ####Example:
259 *
260 * var db = mongoose.createConnection();
261 * db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
262 *
263 * The database name and/or auth need only be included in one URI.
264 * The `options` is a hash which is passed to the internal driver connection object.
265 *
266 * Valid `options`
267 *
268 * db - passed to the connection db instance
269 * server - passed to the connection server instance(s)
270 * replset - passed to the connection ReplSetServer instance
271 * user - username for authentication
272 * pass - password for authentication
273 * auth - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)
274 * mongos - Boolean - if true, enables High Availability support for mongos
275 *
276 * _Options passed take precedence over options included in connection strings._
277 *
278 * ####Notes:
279 *
280 * _If connecting to multiple mongos servers, set the `mongos` option to true._
281 *
282 * conn.open('mongodb://mongosA:27501,mongosB:27501', { mongos: true }, cb);
283 *
284 * Mongoose forces the db option `forceServerObjectId` false and cannot be overridden.
285 * Mongoose defaults the server `auto_reconnect` options to true which can be overridden.
286 * See the node-mongodb-native driver instance for options that it understands.
287 *
288 * _Options passed take precedence over options included in connection strings._
289 *
290 * @param {String} uris comma-separated mongodb:// `URI`s
291 * @param {String} [database] database name if not included in `uris`
292 * @param {Object} [options] passed to the internal driver
293 * @param {Function} [callback]
294 * @see node-mongodb-native https://github.com/mongodb/node-mongodb-native
295 * @see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate
296 * @api public
297 */
298
2991Connection.prototype.openSet = function (uris, database, options, callback) {
3000 if (!rgxProtocol.test(uris)) {
3010 uris = 'mongodb://' + uris;
302 }
303
3040 var self = this;
305
3060 switch (arguments.length) {
307 case 3:
3080 switch (typeof database) {
309 case 'string':
3100 this.name = database;
3110 break;
312 case 'object':
3130 callback = options;
3140 options = database;
3150 database = null;
3160 break;
317 }
318
3190 if ('function' === typeof options) {
3200 callback = options;
3210 options = {};
322 }
3230 break;
324 case 2:
3250 switch (typeof database) {
326 case 'string':
3270 this.name = database;
3280 break;
329 case 'function':
3300 callback = database, database = null;
3310 break;
332 case 'object':
3330 options = database, database = null;
3340 break;
335 }
336 }
337
3380 var parsed;
3390 try {
3400 parsed = muri(uris);
341 } catch (err) {
3420 this.error(err, callback);
3430 return this;
344 }
345
3460 if (!this.name) {
3470 this.name = parsed.db;
348 }
349
3500 this.hosts = parsed.hosts;
3510 this.options = this.parseOptions(options, parsed && parsed.options);
3520 this.replica = true;
353
3540 if (!this.name) {
3550 this.error(new Error('No database name provided for replica set'), callback);
3560 return this;
357 }
358
359 // authentication
3600 if (options && options.user && options.pass) {
3610 this.user = options.user;
3620 this.pass = options.pass;
363
3640 } else if (parsed && parsed.auth) {
3650 this.user = parsed.auth.user;
3660 this.pass = parsed.auth.pass;
367
368 } else {
3690 this.user = this.pass = undefined;
370 }
371
3720 this._open(callback);
3730 return this;
374};
375
376/**
377 * error
378 *
379 * Graceful error handling, passes error to callback
380 * if available, else emits error on the connection.
381 *
382 * @param {Error} err
383 * @param {Function} callback optional
384 * @api private
385 */
386
3871Connection.prototype.error = function (err, callback) {
3880 if (callback) return callback(err);
3890 this.emit('error', err);
390}
391
392/**
393 * Handles opening the connection with the appropriate method based on connection type.
394 *
395 * @param {Function} callback
396 * @api private
397 */
398
3991Connection.prototype._open = function (callback) {
4001 this.readyState = STATES.connecting;
4011 this._closeCalled = false;
402
4031 var self = this;
404
4051 var method = this.replica
406 ? 'doOpenSet'
407 : 'doOpen';
408
409 // open connection
4101 this[method](function (err) {
4110 if (err) {
4120 self.readyState = STATES.disconnected;
4130 if (self._hasOpened) {
4140 if (callback) callback(err);
415 } else {
4160 self.error(err, callback);
417 }
4180 return;
419 }
420
4210 self.onOpen(callback);
422 });
423}
424
425/**
426 * Called when the connection is opened
427 *
428 * @api private
429 */
430
4311Connection.prototype.onOpen = function (callback) {
4320 var self = this;
433
4340 function open (err) {
4350 if (err) {
4360 self.readyState = STATES.disconnected;
4370 if (self._hasOpened) {
4380 if (callback) callback(err);
439 } else {
4400 self.error(err, callback);
441 }
4420 return;
443 }
444
4450 self.readyState = STATES.connected;
446
447 // avoid having the collection subscribe to our event emitter
448 // to prevent 0.3 warning
4490 for (var i in self.collections)
4500 self.collections[i].onOpen();
451
4520 callback && callback();
4530 self.emit('open');
454 };
455
456 // re-authenticate
4570 if (self.user && self.pass) {
4580 self.db.authenticate(self.user, self.pass, self.options.auth, open);
459 }
460 else
4610 open();
462};
463
464/**
465 * Closes the connection
466 *
467 * @param {Function} [callback] optional
468 * @return {Connection} self
469 * @api public
470 */
471
4721Connection.prototype.close = function (callback) {
4730 var self = this;
4740 this._closeCalled = true;
475
4760 switch (this.readyState){
477 case 0: // disconnected
4780 callback && callback();
4790 break;
480
481 case 1: // connected
4820 this.readyState = STATES.disconnecting;
4830 this.doClose(function(err){
4840 if (err){
4850 self.error(err, callback);
486 } else {
4870 self.onClose();
4880 callback && callback();
489 }
490 });
4910 break;
492
493 case 2: // connecting
4940 this.once('open', function(){
4950 self.close(callback);
496 });
4970 break;
498
499 case 3: // disconnecting
5000 if (!callback) break;
5010 this.once('close', function () {
5020 callback();
503 });
5040 break;
505 }
506
5070 return this;
508};
509
510/**
511 * Called when the connection closes
512 *
513 * @api private
514 */
515
5161Connection.prototype.onClose = function () {
5170 this.readyState = STATES.disconnected;
518
519 // avoid having the collection subscribe to our event emitter
520 // to prevent 0.3 warning
5210 for (var i in this.collections)
5220 this.collections[i].onClose();
523
5240 this.emit('close');
525};
526
527/**
528 * Retrieves a collection, creating it if not cached.
529 *
530 * Not typically needed by applications. Just talk to your collection through your model.
531 *
532 * @param {String} name of the collection
533 * @param {Object} [options] optional collection options
534 * @return {Collection} collection instance
535 * @api public
536 */
537
5381Connection.prototype.collection = function (name, options) {
5390 if (!(name in this.collections))
5400 this.collections[name] = new Collection(name, this, options);
5410 return this.collections[name];
542};
543
544/**
545 * Defines or retrieves a model.
546 *
547 * var mongoose = require('mongoose');
548 * var db = mongoose.createConnection(..);
549 * db.model('Venue', new Schema(..));
550 * var Ticket = db.model('Ticket', new Schema(..));
551 * var Venue = db.model('Venue');
552 *
553 * _When no `collection` argument is passed, Mongoose produces a collection name by passing the model `name` to the [utils.toCollectionName](#utils_exports.toCollectionName) method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option._
554 *
555 * ####Example:
556 *
557 * var schema = new Schema({ name: String }, { collection: 'actor' });
558 *
559 * // or
560 *
561 * schema.set('collection', 'actor');
562 *
563 * // or
564 *
565 * var collectionName = 'actor'
566 * var M = conn.model('Actor', schema, collectionName)
567 *
568 * @param {String} name the model name
569 * @param {Schema} [schema] a schema. necessary when defining a model
570 * @param {String} [collection] name of mongodb collection (optional) if not given it will be induced from model name
571 * @see Mongoose#model #index_Mongoose-model
572 * @return {Model} The compiled model
573 * @api public
574 */
575
5761Connection.prototype.model = function (name, schema, collection) {
577 // collection name discovery
5780 if ('string' == typeof schema) {
5790 collection = schema;
5800 schema = false;
581 }
582
5830 if (utils.isObject(schema) && !(schema instanceof Schema)) {
5840 schema = new Schema(schema);
585 }
586
5870 if (this.models[name] && !collection) {
588 // model exists but we are not subclassing with custom collection
5890 if (schema instanceof Schema && schema != this.models[name].schema) {
5900 throw new MongooseError.OverwriteModelError(name);
591 }
5920 return this.models[name];
593 }
594
5950 var opts = { cache: false, connection: this }
5960 var model;
597
5980 if (schema instanceof Schema) {
599 // compile a model
6000 model = this.base.model(name, schema, collection, opts)
601
602 // only the first model with this name is cached to allow
603 // for one-offs with custom collection names etc.
6040 if (!this.models[name]) {
6050 this.models[name] = model;
606 }
607
6080 model.init();
6090 return model;
610 }
611
6120 if (this.models[name] && collection) {
613 // subclassing current model with alternate collection
6140 model = this.models[name];
6150 schema = model.prototype.schema;
6160 var sub = model.__subclass(this, schema, collection);
617 // do not cache the sub model
6180 return sub;
619 }
620
621 // lookup model in mongoose module
6220 model = this.base.models[name];
623
6240 if (!model) {
6250 throw new MongooseError.MissingSchemaError(name);
626 }
627
6280 if (this == model.prototype.db
629 && (!collection || collection == model.collection.name)) {
630 // model already uses this connection.
631
632 // only the first model with this name is cached to allow
633 // for one-offs with custom collection names etc.
6340 if (!this.models[name]) {
6350 this.models[name] = model;
636 }
637
6380 return model;
639 }
640
6410 return this.models[name] = model.__subclass(this, schema, collection);
642}
643
644/**
645 * Returns an array of model names created on this connection.
646 * @api public
647 * @return {Array}
648 */
649
6501Connection.prototype.modelNames = function () {
6510 return Object.keys(this.models);
652}
653
654/**
655 * Set profiling level.
656 *
657 * @param {Number|String} level either off (0), slow (1), or all (2)
658 * @param {Number} [ms] the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
659 * @param {Function} callback
660 * @api public
661 */
662
6631Connection.prototype.setProfiling = function (level, ms, callback) {
6640 if (STATES.connected !== this.readyState) {
6650 return this.on('open', this.setProfiling.bind(this, level, ms, callback));
666 }
667
6680 if (!callback) callback = ms, ms = 100;
669
6700 var cmd = {};
671
6720 switch (level) {
673 case 0:
674 case 'off':
6750 cmd.profile = 0;
6760 break;
677 case 1:
678 case 'slow':
6790 cmd.profile = 1;
6800 if ('number' !== typeof ms) {
6810 ms = parseInt(ms, 10);
6820 if (isNaN(ms)) ms = 100;
683 }
6840 cmd.slowms = ms;
6850 break;
686 case 2:
687 case 'all':
6880 cmd.profile = 2;
6890 break;
690 default:
6910 return callback(new Error('Invalid profiling level: '+ level));
692 }
693
6940 this.db.executeDbCommand(cmd, function (err, resp) {
6950 if (err) return callback(err);
696
6970 var doc = resp.documents[0];
698
6990 err = 1 === doc.ok
700 ? null
701 : new Error('Could not set profiling level to: '+ level)
702
7030 callback(err, doc);
704 });
705};
706
707/*!
708 * Noop.
709 */
710
7111function noop () {}
712
713/*!
714 * Module exports.
715 */
716
7171Connection.STATES = STATES;
7181module.exports = Connection;
719

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/connectionstate.js

100%
16
16
0
LineHitsSource
1
2/*!
3 * Connection states
4 */
5
61var STATES = module.exports = exports = Object.create(null);
7
81var disconnected = 'disconnected';
91var connected = 'connected';
101var connecting = 'connecting';
111var disconnecting = 'disconnecting';
121var uninitialized = 'uninitialized';
13
141STATES[0] = disconnected;
151STATES[1] = connected;
161STATES[2] = connecting;
171STATES[3] = disconnecting;
181STATES[99] = uninitialized;
19
201STATES[disconnected] = 0;
211STATES[connected] = 1;
221STATES[connecting] = 2;
231STATES[disconnecting] = 3;
241STATES[uninitialized] = 99;
25

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/document.js

9%
531
50
481
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var EventEmitter = require('events').EventEmitter
6 , setMaxListeners = EventEmitter.prototype.setMaxListeners
7 , MongooseError = require('./error')
8 , MixedSchema = require('./schema/mixed')
9 , Schema = require('./schema')
10 , ValidatorError = require('./schematype').ValidatorError
11 , utils = require('./utils')
12 , clone = utils.clone
13 , isMongooseObject = utils.isMongooseObject
14 , inspect = require('util').inspect
15 , ElemMatchError = MongooseError.ElemMatchError
16 , ValidationError = MongooseError.ValidationError
17 , InternalCache = require('./internal')
18 , deepEqual = utils.deepEqual
19 , hooks = require('hooks')
20 , DocumentArray
21 , MongooseArray
22 , Embedded
23
24/**
25 * Document constructor.
26 *
27 * @param {Object} obj the values to set
28 * @param {Object} [opts] optional object containing the fields which were selected in the query returning this document and any populated paths data
29 * @param {Boolean} [skipId] bool, should we auto create an ObjectId _id
30 * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
31 * @event `init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.
32 * @event `save`: Emitted when the document is successfully saved
33 * @api private
34 */
35
361function Document (obj, fields, skipId) {
370 this.$__ = new InternalCache;
380 this.isNew = true;
390 this.errors = undefined;
40
410 var schema = this.schema;
42
430 if ('boolean' === typeof fields) {
440 this.$__.strictMode = fields;
450 fields = undefined;
46 } else {
470 this.$__.strictMode = schema.options && schema.options.strict;
480 this.$__.selected = fields;
49 }
50
510 var required = schema.requiredPaths();
520 for (var i = 0; i < required.length; ++i) {
530 this.$__.activePaths.require(required[i]);
54 }
55
560 setMaxListeners.call(this, 0);
570 this._doc = this.$__buildDoc(obj, fields, skipId);
58
590 if (obj) {
600 this.set(obj, undefined, true);
61 }
62
630 this.$__registerHooks();
64}
65
66/*!
67 * Inherit from EventEmitter.
68 */
69
701Document.prototype.__proto__ = EventEmitter.prototype;
71
72/**
73 * The documents schema.
74 *
75 * @api public
76 * @property schema
77 */
78
791Document.prototype.schema;
80
81/**
82 * Boolean flag specifying if the document is new.
83 *
84 * @api public
85 * @property isNew
86 */
87
881Document.prototype.isNew;
89
90/**
91 * The string version of this documents _id.
92 *
93 * ####Note:
94 *
95 * This getter exists on all documents by default. The getter can be disabled by setting the `id` [option](/docs/guide.html#id) of its `Schema` to false at construction time.
96 *
97 * new Schema({ name: String }, { id: false });
98 *
99 * @api public
100 * @see Schema options /docs/guide.html#options
101 * @property id
102 */
103
1041Document.prototype.id;
105
106/**
107 * Hash containing current validation errors.
108 *
109 * @api public
110 * @property errors
111 */
112
1131Document.prototype.errors;
114
115/**
116 * Builds the default doc structure
117 *
118 * @param {Object} obj
119 * @param {Object} [fields]
120 * @param {Boolean} [skipId]
121 * @return {Object}
122 * @api private
123 * @method $__buildDoc
124 * @memberOf Document
125 */
126
1271Document.prototype.$__buildDoc = function (obj, fields, skipId) {
1280 var doc = {}
129 , self = this
130 , exclude
131 , keys
132 , key
133 , ki
134
135 // determine if this doc is a result of a query with
136 // excluded fields
1370 if (fields && 'Object' === fields.constructor.name) {
1380 keys = Object.keys(fields);
1390 ki = keys.length;
140
1410 while (ki--) {
1420 if ('_id' !== keys[ki]) {
1430 exclude = 0 === fields[keys[ki]];
1440 break;
145 }
146 }
147 }
148
1490 var paths = Object.keys(this.schema.paths)
150 , plen = paths.length
151 , ii = 0
152
1530 for (; ii < plen; ++ii) {
1540 var p = paths[ii];
155
1560 if ('_id' == p) {
1570 if (skipId) continue;
1580 if (obj && '_id' in obj) continue;
159 }
160
1610 var type = this.schema.paths[p]
162 , path = p.split('.')
163 , len = path.length
164 , last = len-1
165 , curPath = ''
166 , doc_ = doc
167 , i = 0
168
1690 for (; i < len; ++i) {
1700 var piece = path[i]
171 , def
172
173 // support excluding intermediary levels
1740 if (exclude) {
1750 curPath += piece;
1760 if (curPath in fields) break;
1770 curPath += '.';
178 }
179
1800 if (i === last) {
1810 if (fields) {
1820 if (exclude) {
183 // apply defaults to all non-excluded fields
1840 if (p in fields) continue;
185
1860 def = type.getDefault(self, true);
1870 if ('undefined' !== typeof def) {
1880 doc_[piece] = def;
1890 self.$__.activePaths.default(p);
190 }
191
1920 } else if (p in fields) {
193 // selected field
1940 def = type.getDefault(self, true);
1950 if ('undefined' !== typeof def) {
1960 doc_[piece] = def;
1970 self.$__.activePaths.default(p);
198 }
199 }
200 } else {
2010 def = type.getDefault(self, true);
2020 if ('undefined' !== typeof def) {
2030 doc_[piece] = def;
2040 self.$__.activePaths.default(p);
205 }
206 }
207 } else {
2080 doc_ = doc_[piece] || (doc_[piece] = {});
209 }
210 }
211 };
212
2130 return doc;
214};
215
216/**
217 * Initializes the document without setters or marking anything modified.
218 *
219 * Called internally after a document is returned from mongodb.
220 *
221 * @param {Object} doc document returned by mongo
222 * @param {Function} fn callback
223 * @api private
224 */
225
2261Document.prototype.init = function (doc, opts, fn) {
227 // do not prefix this method with $__ since its
228 // used by public hooks
229
2300 if ('function' == typeof opts) {
2310 fn = opts;
2320 opts = null;
233 }
234
2350 this.isNew = false;
236
237 // handle docs with populated paths
2380 if (doc._id && opts && opts.populated && opts.populated.length) {
2390 var id = String(doc._id);
2400 for (var i = 0; i < opts.populated.length; ++i) {
2410 var item = opts.populated[i];
2420 this.populated(item.path, item._docs[id], item);
243 }
244 }
245
2460 init(this, doc, this._doc);
2470 this.$__storeShard();
248
2490 this.emit('init', this);
2500 if (fn) fn(null);
2510 return this;
252};
253
254/*!
255 * Init helper.
256 *
257 * @param {Object} self document instance
258 * @param {Object} obj raw mongodb doc
259 * @param {Object} doc object we are initializing
260 * @api private
261 */
262
2631function init (self, obj, doc, prefix) {
2640 prefix = prefix || '';
265
2660 var keys = Object.keys(obj)
267 , len = keys.length
268 , schema
269 , path
270 , i;
271
2720 while (len--) {
2730 i = keys[len];
2740 path = prefix + i;
2750 schema = self.schema.path(path);
276
2770 if (!schema && utils.isObject(obj[i]) &&
278 (!obj[i].constructor || 'Object' == obj[i].constructor.name)) {
279 // assume nested object
2800 if (!doc[i]) doc[i] = {};
2810 init(self, obj[i], doc[i], path + '.');
282 } else {
2830 if (obj[i] === null) {
2840 doc[i] = null;
2850 } else if (obj[i] !== undefined) {
2860 if (schema) {
2870 self.$__try(function(){
2880 doc[i] = schema.cast(obj[i], self, true);
289 });
290 } else {
2910 doc[i] = obj[i];
292 }
293 }
294 // mark as hydrated
2950 self.$__.activePaths.init(path);
296 }
297 }
298};
299
300/**
301 * Stores the current values of the shard keys.
302 *
303 * ####Note:
304 *
305 * _Shard key values do not / are not allowed to change._
306 *
307 * @api private
308 * @method $__storeShard
309 * @memberOf Document
310 */
311
3121Document.prototype.$__storeShard = function () {
313 // backwards compat
3140 var key = this.schema.options.shardKey || this.schema.options.shardkey;
3150 if (!(key && 'Object' == key.constructor.name)) return;
316
3170 var orig = this.$__.shardval = {}
318 , paths = Object.keys(key)
319 , len = paths.length
320 , val
321
3220 for (var i = 0; i < len; ++i) {
3230 val = this.getValue(paths[i]);
3240 if (isMongooseObject(val)) {
3250 orig[paths[i]] = val.toObject({ depopulate: true })
3260 } else if (null != val && val.valueOf) {
3270 orig[paths[i]] = val.valueOf();
328 } else {
3290 orig[paths[i]] = val;
330 }
331 }
332}
333
334/*!
335 * Set up middleware support
336 */
337
3381for (var k in hooks) {
3395 Document.prototype[k] = Document[k] = hooks[k];
340}
341
342/**
343 * Sends an update command with this document `_id` as the query selector.
344 *
345 * ####Example:
346 *
347 * weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);
348 *
349 * ####Valid options:
350 *
351 * - same as in [Model.update](#model_Model.update)
352 *
353 * @see Model.update #model_Model.update
354 * @param {Object} doc
355 * @param {Object} options
356 * @param {Function} callback
357 * @return {Query}
358 * @api public
359 */
360
3611Document.prototype.update = function update () {
3620 var args = utils.args(arguments);
3630 args.unshift({_id: this._id});
3640 return this.constructor.update.apply(this.constructor, args);
365}
366
367/**
368 * Sets the value of a path, or many paths.
369 *
370 * ####Example:
371 *
372 * // path, value
373 * doc.set(path, value)
374 *
375 * // object
376 * doc.set({
377 * path : value
378 * , path2 : {
379 * path : value
380 * }
381 * })
382 *
383 * // only-the-fly cast to number
384 * doc.set(path, value, Number)
385 *
386 * // only-the-fly cast to string
387 * doc.set(path, value, String)
388 *
389 * // changing strict mode behavior
390 * doc.set(path, value, { strict: false });
391 *
392 * @param {String|Object} path path or object of key/vals to set
393 * @param {Any} val the value to set
394 * @param {Schema|String|Number|Buffer|etc..} [type] optionally specify a type for "on-the-fly" attributes
395 * @param {Object} [options] optionally specify options that modify the behavior of the set
396 * @api public
397 */
398
3991Document.prototype.set = function (path, val, type, options) {
4000 if (type && 'Object' == type.constructor.name) {
4010 options = type;
4020 type = undefined;
403 }
404
4050 var merge = options && options.merge
406 , adhoc = type && true !== type
407 , constructing = true === type
408 , adhocs
409
4100 var strict = options && 'strict' in options
411 ? options.strict
412 : this.$__.strictMode;
413
4140 if (adhoc) {
4150 adhocs = this.$__.adhocPaths || (this.$__.adhocPaths = {});
4160 adhocs[path] = Schema.interpretAsType(path, type);
417 }
418
4190 if ('string' !== typeof path) {
420 // new Document({ key: val })
421
4220 if (null === path || undefined === path) {
4230 var _ = path;
4240 path = val;
4250 val = _;
426
427 } else {
4280 var prefix = val
429 ? val + '.'
430 : '';
431
4320 if (path instanceof Document) path = path._doc;
433
4340 var keys = Object.keys(path)
435 , i = keys.length
436 , pathtype
437 , key
438
439
4400 while (i--) {
4410 key = keys[i];
4420 pathtype = this.schema.pathType(prefix + key);
4430 if (null != path[key]
444 // need to know if plain object - no Buffer, ObjectId, ref, etc
445 && utils.isObject(path[key])
446 && (!path[key].constructor || 'Object' == path[key].constructor.name)
447 && 'virtual' != pathtype
448 && !(this.$__path(prefix + key) instanceof MixedSchema)
449 && !(this.schema.paths[key] && this.schema.paths[key].options.ref)
450 ) {
4510 this.set(path[key], prefix + key, constructing);
4520 } else if (strict) {
4530 if ('real' === pathtype || 'virtual' === pathtype) {
4540 this.set(prefix + key, path[key], constructing);
4550 } else if ('throw' == strict) {
4560 throw new Error("Field `" + key + "` is not in schema.");
457 }
4580 } else if (undefined !== path[key]) {
4590 this.set(prefix + key, path[key], constructing);
460 }
461 }
462
4630 return this;
464 }
465 }
466
467 // ensure _strict is honored for obj props
468 // docschema = new Schema({ path: { nest: 'string' }})
469 // doc.set('path', obj);
4700 var pathType = this.schema.pathType(path);
4710 if ('nested' == pathType && val && utils.isObject(val) &&
472 (!val.constructor || 'Object' == val.constructor.name)) {
4730 if (!merge) this.setValue(path, null);
4740 this.set(val, path, constructing);
4750 return this;
476 }
477
4780 var schema;
4790 var parts = path.split('.');
480
4810 if ('adhocOrUndefined' == pathType && strict) {
482
483 // check for roots that are Mixed types
4840 var mixed;
485
4860 for (var i = 0; i < parts.length; ++i) {
4870 var subpath = parts.slice(0, i+1).join('.');
4880 schema = this.schema.path(subpath);
4890 if (schema instanceof MixedSchema) {
490 // allow changes to sub paths of mixed types
4910 mixed = true;
4920 break;
493 }
494 }
495
4960 if (!mixed) {
4970 if ('throw' == strict) {
4980 throw new Error("Field `" + path + "` is not in schema.");
499 }
5000 return this;
501 }
502
5030 } else if ('virtual' == pathType) {
5040 schema = this.schema.virtualpath(path);
5050 schema.applySetters(val, this);
5060 return this;
507 } else {
5080 schema = this.$__path(path);
509 }
510
5110 var pathToMark;
512
513 // When using the $set operator the path to the field must already exist.
514 // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
515
5160 if (parts.length <= 1) {
5170 pathToMark = path;
518 } else {
5190 for (var i = 0; i < parts.length; ++i) {
5200 var subpath = parts.slice(0, i+1).join('.');
5210 if (this.isDirectModified(subpath) // earlier prefixes that are already
522 // marked as dirty have precedence
523 || this.get(subpath) === null) {
5240 pathToMark = subpath;
5250 break;
526 }
527 }
528
5290 if (!pathToMark) pathToMark = path;
530 }
531
532 // if this doc is being constructed we should not trigger getters
5330 var priorVal = constructing
534 ? undefined
535 : this.get(path);
536
5370 if (!schema || undefined === val) {
5380 this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal);
5390 return this;
540 }
541
5420 var self = this;
5430 var shouldSet = this.$__try(function(){
5440 val = schema.applySetters(val, self, false, priorVal);
545 });
546
5470 if (shouldSet) {
5480 this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal);
549 }
550
5510 return this;
552}
553
554/**
555 * Determine if we should mark this change as modified.
556 *
557 * @return {Boolean}
558 * @api private
559 * @method $__shouldModify
560 * @memberOf Document
561 */
562
5631Document.prototype.$__shouldModify = function (
564 pathToMark, path, constructing, parts, schema, val, priorVal) {
565
5660 if (this.isNew) return true;
5670 if (this.isDirectModified(pathToMark)) return false;
568
5690 if (undefined === val && !this.isSelected(path)) {
570 // when a path is not selected in a query, its initial
571 // value will be undefined.
5720 return true;
573 }
574
5750 if (undefined === val && path in this.$__.activePaths.states.default) {
576 // we're just unsetting the default value which was never saved
5770 return false;
578 }
579
5800 if (!deepEqual(val, priorVal || this.get(path))) {
5810 return true;
582 }
583
5840 if (!constructing &&
585 null != val &&
586 path in this.$__.activePaths.states.default &&
587 deepEqual(val, schema.getDefault(this, constructing))) {
588 // a path with a default was $unset on the server
589 // and the user is setting it to the same value again
5900 return true;
591 }
592
5930 return false;
594}
595
596/**
597 * Handles the actual setting of the value and marking the path modified if appropriate.
598 *
599 * @api private
600 * @method $__set
601 * @memberOf Document
602 */
603
6041Document.prototype.$__set = function (
605 pathToMark, path, constructing, parts, schema, val, priorVal) {
606
6070 var shouldModify = this.$__shouldModify.apply(this, arguments);
608
6090 if (shouldModify) {
6100 this.markModified(pathToMark, val);
611
612 // handle directly setting arrays (gh-1126)
6130 MongooseArray || (MongooseArray = require('./types/array'));
6140 if (val instanceof MongooseArray) {
6150 val._registerAtomic('$set', val);
616 }
617 }
618
6190 var obj = this._doc
620 , i = 0
621 , l = parts.length
622
6230 for (; i < l; i++) {
6240 var next = i + 1
625 , last = next === l;
626
6270 if (last) {
6280 obj[parts[i]] = val;
629 } else {
6300 if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
6310 obj = obj[parts[i]];
6320 } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
6330 obj = obj[parts[i]];
634 } else {
6350 obj = obj[parts[i]] = {};
636 }
637 }
638 }
639}
640
641/**
642 * Gets a raw value from a path (no getters)
643 *
644 * @param {String} path
645 * @api private
646 */
647
6481Document.prototype.getValue = function (path) {
6490 return utils.getValue(path, this._doc);
650}
651
652/**
653 * Sets a raw value for a path (no casting, setters, transformations)
654 *
655 * @param {String} path
656 * @param {Object} value
657 * @api private
658 */
659
6601Document.prototype.setValue = function (path, val) {
6610 utils.setValue(path, val, this._doc);
6620 return this;
663}
664
665/**
666 * Returns the value of a path.
667 *
668 * ####Example
669 *
670 * // path
671 * doc.get('age') // 47
672 *
673 * // dynamic casting to a string
674 * doc.get('age', String) // "47"
675 *
676 * @param {String} path
677 * @param {Schema|String|Number|Buffer|etc..} [type] optionally specify a type for on-the-fly attributes
678 * @api public
679 */
680
6811Document.prototype.get = function (path, type) {
6820 var adhocs;
6830 if (type) {
6840 adhocs = this.$__.adhocPaths || (this.$__.adhocPaths = {});
6850 adhocs[path] = Schema.interpretAsType(path, type);
686 }
687
6880 var schema = this.$__path(path) || this.schema.virtualpath(path)
689 , pieces = path.split('.')
690 , obj = this._doc;
691
6920 for (var i = 0, l = pieces.length; i < l; i++) {
6930 obj = undefined === obj || null === obj
694 ? undefined
695 : obj[pieces[i]];
696 }
697
6980 if (schema) {
6990 obj = schema.applyGetters(obj, this);
700 }
701
7020 return obj;
703};
704
705/**
706 * Returns the schematype for the given `path`.
707 *
708 * @param {String} path
709 * @api private
710 * @method $__path
711 * @memberOf Document
712 */
713
7141Document.prototype.$__path = function (path) {
7150 var adhocs = this.$__.adhocPaths
716 , adhocType = adhocs && adhocs[path];
717
7180 if (adhocType) {
7190 return adhocType;
720 } else {
7210 return this.schema.path(path);
722 }
723};
724
725/**
726 * Marks the path as having pending changes to write to the db.
727 *
728 * _Very helpful when using [Mixed](./schematypes.html#mixed) types._
729 *
730 * ####Example:
731 *
732 * doc.mixed.type = 'changed';
733 * doc.markModified('mixed.type');
734 * doc.save() // changes to mixed.type are now persisted
735 *
736 * @param {String} path the path to mark modified
737 * @api public
738 */
739
7401Document.prototype.markModified = function (path) {
7410 this.$__.activePaths.modify(path);
742}
743
744/**
745 * Catches errors that occur during execution of `fn` and stores them to later be passed when `save()` is executed.
746 *
747 * @param {Function} fn function to execute
748 * @param {Object} scope the scope with which to call fn
749 * @api private
750 * @method $__try
751 * @memberOf Document
752 */
753
7541Document.prototype.$__try = function (fn, scope) {
7550 var res;
7560 try {
7570 fn.call(scope);
7580 res = true;
759 } catch (e) {
7600 this.$__error(e);
7610 res = false;
762 }
7630 return res;
764};
765
766/**
767 * Returns the list of paths that have been modified.
768 *
769 * @return {Array}
770 * @api public
771 */
772
7731Document.prototype.modifiedPaths = function () {
7740 var directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
775
7760 return directModifiedPaths.reduce(function (list, path) {
7770 var parts = path.split('.');
7780 return list.concat(parts.reduce(function (chains, part, i) {
7790 return chains.concat(parts.slice(0, i).concat(part).join('.'));
780 }, []));
781 }, []);
782};
783
784/**
785 * Returns true if this document was modified, else false.
786 *
787 * If `path` is given, checks if a path or any full path containing `path` as part of its path chain has been modified.
788 *
789 * ####Example
790 *
791 * doc.set('documents.0.title', 'changed');
792 * doc.isModified() // true
793 * doc.isModified('documents') // true
794 * doc.isModified('documents.0.title') // true
795 * doc.isDirectModified('documents') // false
796 *
797 * @param {String} [path] optional
798 * @return {Boolean}
799 * @api public
800 */
801
8021Document.prototype.isModified = function (path) {
8030 return path
804 ? !!~this.modifiedPaths().indexOf(path)
805 : this.$__.activePaths.some('modify');
806};
807
808/**
809 * Returns true if `path` was directly set and modified, else false.
810 *
811 * ####Example
812 *
813 * doc.set('documents.0.title', 'changed');
814 * doc.isDirectModified('documents.0.title') // true
815 * doc.isDirectModified('documents') // false
816 *
817 * @param {String} path
818 * @return {Boolean}
819 * @api public
820 */
821
8221Document.prototype.isDirectModified = function (path) {
8230 return (path in this.$__.activePaths.states.modify);
824};
825
826/**
827 * Checks if `path` was initialized.
828 *
829 * @param {String} path
830 * @return {Boolean}
831 * @api public
832 */
833
8341Document.prototype.isInit = function (path) {
8350 return (path in this.$__.activePaths.states.init);
836};
837
838/**
839 * Checks if `path` was selected in the source query which initialized this document.
840 *
841 * ####Example
842 *
843 * Thing.findOne().select('name').exec(function (err, doc) {
844 * doc.isSelected('name') // true
845 * doc.isSelected('age') // false
846 * })
847 *
848 * @param {String} path
849 * @return {Boolean}
850 * @api public
851 */
852
8531Document.prototype.isSelected = function isSelected (path) {
8540 if (this.$__.selected) {
855
8560 if ('_id' === path) {
8570 return 0 !== this.$__.selected._id;
858 }
859
8600 var paths = Object.keys(this.$__.selected)
861 , i = paths.length
862 , inclusive = false
863 , cur
864
8650 if (1 === i && '_id' === paths[0]) {
866 // only _id was selected.
8670 return 0 === this.$__.selected._id;
868 }
869
8700 while (i--) {
8710 cur = paths[i];
8720 if ('_id' == cur) continue;
8730 inclusive = !! this.$__.selected[cur];
8740 break;
875 }
876
8770 if (path in this.$__.selected) {
8780 return inclusive;
879 }
880
8810 i = paths.length;
8820 var pathDot = path + '.';
883
8840 while (i--) {
8850 cur = paths[i];
8860 if ('_id' == cur) continue;
887
8880 if (0 === cur.indexOf(pathDot)) {
8890 return inclusive;
890 }
891
8920 if (0 === pathDot.indexOf(cur + '.')) {
8930 return inclusive;
894 }
895 }
896
8970 return ! inclusive;
898 }
899
9000 return true;
901}
902
903/**
904 * Executes registered validation rules for this document.
905 *
906 * ####Note:
907 *
908 * This method is called `pre` save and if a validation rule is violated, [save](#model_Model-save) is aborted and the error is returned to your `callback`.
909 *
910 * ####Example:
911 *
912 * doc.validate(function (err) {
913 * if (err) handleError(err);
914 * else // validation passed
915 * });
916 *
917 * @param {Function} cb called after validation completes, passing an error if one occurred
918 * @api public
919 */
920
9211Document.prototype.validate = function (cb) {
9220 var self = this
923
924 // only validate required fields when necessary
9250 var paths = Object.keys(this.$__.activePaths.states.require).filter(function (path) {
9260 if (!self.isSelected(path) && !self.isModified(path)) return false;
9270 return true;
928 });
929
9300 paths = paths.concat(Object.keys(this.$__.activePaths.states.init));
9310 paths = paths.concat(Object.keys(this.$__.activePaths.states.modify));
9320 paths = paths.concat(Object.keys(this.$__.activePaths.states.default));
933
9340 if (0 === paths.length) {
9350 complete();
9360 return this;
937 }
938
9390 var validating = {}
940 , total = 0;
941
9420 paths.forEach(validatePath);
9430 return this;
944
9450 function validatePath (path) {
9460 if (validating[path]) return;
947
9480 validating[path] = true;
9490 total++;
950
9510 process.nextTick(function(){
9520 var p = self.schema.path(path);
9530 if (!p) return --total || complete();
954
9550 var val = self.getValue(path);
9560 p.doValidate(val, function (err) {
9570 if (err) {
9580 self.invalidate(
959 path
960 , err
961 , undefined
962 , true // embedded docs
963 );
964 }
9650 --total || complete();
966 }, self);
967 });
968 }
969
9700 function complete () {
9710 var err = self.$__.validationError;
9720 self.$__.validationError = undefined;
9730 self.emit('validate', self);
9740 cb(err);
975 }
976};
977
978/**
979 * Marks a path as invalid, causing validation to fail.
980 *
981 * The `errorMsg` argument will become the message of the `ValidationError`.
982 *
983 * The `value` argument (if passed) will be available through the `ValidationError.value` property.
984 *
985 * doc.invalidate('size', 'must be less than 20', 14);
986
987 * doc.validate(function (err) {
988 * console.log(err)
989 * // prints
990 * { message: 'Validation failed',
991 * name: 'ValidationError',
992 * errors:
993 * { size:
994 * { message: 'must be less than 20',
995 * name: 'ValidatorError',
996 * path: 'size',
997 * type: 'user defined',
998 * value: 14 } } }
999 * })
1000 *
1001 * @param {String} path the field to invalidate
1002 * @param {String|Error} errorMsg the error which states the reason `path` was invalid
1003 * @param {Object|String|Number|any} value optional invalid value
1004 * @api public
1005 */
1006
10071Document.prototype.invalidate = function (path, err, val) {
10080 if (!this.$__.validationError) {
10090 this.$__.validationError = new ValidationError(this);
1010 }
1011
10120 if (!err || 'string' === typeof err) {
10130 err = new ValidatorError(path, err, 'user defined', val)
1014 }
1015
10160 if (this.$__.validationError == err) return;
1017
10180 this.$__.validationError.errors[path] = err;
1019}
1020
1021/**
1022 * Resets the internal modified state of this document.
1023 *
1024 * @api private
1025 * @return {Document}
1026 * @method $__reset
1027 * @memberOf Document
1028 */
1029
10301Document.prototype.$__reset = function reset () {
10310 var self = this;
10320 DocumentArray || (DocumentArray = require('./types/documentarray'));
1033
10340 this.$__.activePaths
1035 .map('init', 'modify', function (i) {
10360 return self.getValue(i);
1037 })
1038 .filter(function (val) {
10390 return val && val instanceof DocumentArray && val.length;
1040 })
1041 .forEach(function (array) {
10420 var i = array.length;
10430 while (i--) {
10440 var doc = array[i];
10450 if (!doc) continue;
10460 doc.$__reset();
1047 }
1048 });
1049
1050 // clear atomics
10510 this.$__dirty().forEach(function (dirt) {
10520 var type = dirt.value;
10530 if (type && type._atomics) {
10540 type._atomics = {};
1055 }
1056 });
1057
1058 // Clear 'modify'('dirty') cache
10590 this.$__.activePaths.clear('modify');
10600 this.$__.validationError = undefined;
10610 this.errors = undefined;
10620 var self = this;
10630 this.schema.requiredPaths().forEach(function (path) {
10640 self.$__.activePaths.require(path);
1065 });
1066
10670 return this;
1068}
1069
1070/**
1071 * Returns this documents dirty paths / vals.
1072 *
1073 * @api private
1074 * @method $__dirty
1075 * @memberOf Document
1076 */
1077
10781Document.prototype.$__dirty = function () {
10790 var self = this;
1080
10810 var all = this.$__.activePaths.map('modify', function (path) {
10820 return { path: path
1083 , value: self.getValue(path)
1084 , schema: self.$__path(path) };
1085 });
1086
1087 // Sort dirty paths in a flat hierarchy.
10880 all.sort(function (a, b) {
10890 return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
1090 });
1091
1092 // Ignore "foo.a" if "foo" is dirty already.
10930 var minimal = []
1094 , lastPath
1095 , top;
1096
10970 all.forEach(function (item, i) {
10980 if (item.path.indexOf(lastPath) !== 0) {
10990 lastPath = item.path + '.';
11000 minimal.push(item);
11010 top = item;
1102 } else {
1103 // special case for top level MongooseArrays
11040 if (top.value && top.value._atomics && top.value.hasAtomics()) {
1105 // the `top` array itself and a sub path of `top` are being modified.
1106 // the only way to honor all of both modifications is through a $set
1107 // of entire array.
11080 top.value._atomics = {};
11090 top.value._atomics.$set = top.value;
1110 }
1111 }
1112 });
1113
11140 top = lastPath = null;
11150 return minimal;
1116}
1117
1118/*!
1119 * Compiles schemas.
1120 */
1121
11221function compile (tree, proto, prefix) {
11230 var keys = Object.keys(tree)
1124 , i = keys.length
1125 , limb
1126 , key;
1127
11280 while (i--) {
11290 key = keys[i];
11300 limb = tree[key];
1131
11320 define(key
1133 , (('Object' === limb.constructor.name
1134 && Object.keys(limb).length)
1135 && (!limb.type || limb.type.type)
1136 ? limb
1137 : null)
1138 , proto
1139 , prefix
1140 , keys);
1141 }
1142};
1143
1144/*!
1145 * Defines the accessor named prop on the incoming prototype.
1146 */
1147
11481function define (prop, subprops, prototype, prefix, keys) {
11490 var prefix = prefix || ''
1150 , path = (prefix ? prefix + '.' : '') + prop;
1151
11520 if (subprops) {
1153
11540 Object.defineProperty(prototype, prop, {
1155 enumerable: true
1156 , get: function () {
11570 if (!this.$__.getters)
11580 this.$__.getters = {};
1159
11600 if (!this.$__.getters[path]) {
11610 var nested = Object.create(this);
1162
1163 // save scope for nested getters/setters
11640 if (!prefix) nested.$__.scope = this;
1165
1166 // shadow inherited getters from sub-objects so
1167 // thing.nested.nested.nested... doesn't occur (gh-366)
11680 var i = 0
1169 , len = keys.length;
1170
11710 for (; i < len; ++i) {
1172 // over-write the parents getter without triggering it
11730 Object.defineProperty(nested, keys[i], {
1174 enumerable: false // It doesn't show up.
1175 , writable: true // We can set it later.
1176 , configurable: true // We can Object.defineProperty again.
1177 , value: undefined // It shadows its parent.
1178 });
1179 }
1180
11810 nested.toObject = function () {
11820 return this.get(path);
1183 };
1184
11850 compile(subprops, nested, path);
11860 this.$__.getters[path] = nested;
1187 }
1188
11890 return this.$__.getters[path];
1190 }
1191 , set: function (v) {
11920 if (v instanceof Document) v = v.toObject();
11930 return (this.$__.scope || this).set(path, v);
1194 }
1195 });
1196
1197 } else {
1198
11990 Object.defineProperty(prototype, prop, {
1200 enumerable: true
12010 , get: function ( ) { return this.get.call(this.$__.scope || this, path); }
12020 , set: function (v) { return this.set.call(this.$__.scope || this, path, v); }
1203 });
1204 }
1205};
1206
1207/**
1208 * Assigns/compiles `schema` into this documents prototype.
1209 *
1210 * @param {Schema} schema
1211 * @api private
1212 * @method $__setSchema
1213 * @memberOf Document
1214 */
1215
12161Document.prototype.$__setSchema = function (schema) {
12170 compile(schema.tree, this);
12180 this.schema = schema;
1219}
1220
1221/**
1222 * Register default hooks
1223 *
1224 * @api private
1225 * @method $__registerHooks
1226 * @memberOf Document
1227 */
1228
12291Document.prototype.$__registerHooks = function () {
12300 if (!this.save) return;
1231
12320 DocumentArray || (DocumentArray = require('./types/documentarray'));
1233
12340 this.pre('save', function (next) {
1235 // validate all document arrays.
1236 // we keep the error semaphore to make sure we don't
1237 // call `save` unnecessarily (we only need 1 error)
12380 var subdocs = 0
1239 , error = false
1240 , self = this;
1241
1242 // check for DocumentArrays
12430 var arrays = this.$__.activePaths
1244 .map('init', 'modify', function (i) {
12450 return self.getValue(i);
1246 })
1247 .filter(function (val) {
12480 return val && val instanceof DocumentArray && val.length;
1249 });
1250
12510 if (!arrays.length)
12520 return next();
1253
12540 arrays.forEach(function (array) {
12550 if (error) return;
1256
1257 // handle sparse arrays by using for loop vs array.forEach
1258 // which skips the sparse elements
1259
12600 var len = array.length
12610 subdocs += len;
1262
12630 for (var i = 0; i < len; ++i) {
12640 if (error) break;
1265
12660 var doc = array[i];
12670 if (!doc) {
12680 --subdocs || next();
12690 continue;
1270 }
1271
12720 doc.save(handleSave);
1273 }
1274 });
1275
12760 function handleSave (err) {
12770 if (error) return;
1278
12790 if (err) {
12800 self.$__.validationError = undefined;
12810 return next(error = err);
1282 }
1283
12840 --subdocs || next();
1285 }
1286
1287 }, function (err) {
1288 // emit on the Model if listening
12890 if (this.constructor.listeners('error').length) {
12900 this.constructor.emit('error', err);
1291 } else {
1292 // emit on the connection
12930 if (!this.db.listeners('error').length) {
12940 err.stack = 'No listeners detected, throwing. '
1295 + 'Consider adding an error listener to your connection.\n'
1296 + err.stack
1297 }
12980 this.db.emit('error', err);
1299 }
1300 }).pre('save', function checkForExistingErrors (next) {
1301 // if any doc.set() calls failed
13020 var err = this.$__.saveError;
13030 if (err) {
13040 this.$__.saveError = null;
13050 next(err);
1306 } else {
13070 next();
1308 }
1309 }).pre('save', function validation (next) {
13100 return this.validate(next);
1311 });
1312
1313 // add user defined queues
13140 this.$__doQueue();
1315};
1316
1317/**
1318 * Registers an error
1319 *
1320 * @param {Error} err
1321 * @api private
1322 * @method $__error
1323 * @memberOf Document
1324 */
1325
13261Document.prototype.$__error = function (err) {
13270 this.$__.saveError = err;
13280 return this;
1329};
1330
1331/**
1332 * Executes methods queued from the Schema definition
1333 *
1334 * @api private
1335 * @method $__doQueue
1336 * @memberOf Document
1337 */
1338
13391Document.prototype.$__doQueue = function () {
13400 var q = this.schema && this.schema.callQueue;
13410 if (q) {
13420 for (var i = 0, l = q.length; i < l; i++) {
13430 this[q[i][0]].apply(this, q[i][1]);
1344 }
1345 }
13460 return this;
1347};
1348
1349/**
1350 * Converts this document into a plain javascript object, ready for storage in MongoDB.
1351 *
1352 * Buffers are converted to instances of [mongodb.Binary](http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html) for proper storage.
1353 *
1354 * ####Options:
1355 *
1356 * - `getters` apply all getters (path and virtual getters)
1357 * - `virtuals` apply virtual getters (can override `getters` option)
1358 * - `minimize` remove empty objects (defaults to true)
1359 * - `transform` a transform function to apply to the resulting document before returning
1360 *
1361 * ####Getters/Virtuals
1362 *
1363 * Example of only applying path getters
1364 *
1365 * doc.toObject({ getters: true, virtuals: false })
1366 *
1367 * Example of only applying virtual getters
1368 *
1369 * doc.toObject({ virtuals: true })
1370 *
1371 * Example of applying both path and virtual getters
1372 *
1373 * doc.toObject({ getters: true })
1374 *
1375 * To apply these options to every document of your schema by default, set your [schemas](#schema_Schema) `toObject` option to the same argument.
1376 *
1377 * schema.set('toObject', { virtuals: true })
1378 *
1379 * ####Transform
1380 *
1381 * We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional `transform` function.
1382 *
1383 * Transform functions receive three arguments
1384 *
1385 * function (doc, ret, options) {}
1386 *
1387 * - `doc` The mongoose document which is being converted
1388 * - `ret` The plain object representation which has been converted
1389 * - `options` The options in use (either schema options or the options passed inline)
1390 *
1391 * ####Example
1392 *
1393 * // specify the transform schema option
1394 * if (!schema.options.toObject) schema.options.toObject = {};
1395 * schema.options.toObject.transform = function (doc, ret, options) {
1396 * // remove the _id of every document before returning the result
1397 * delete ret._id;
1398 * }
1399 *
1400 * // without the transformation in the schema
1401 * doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
1402 *
1403 * // with the transformation
1404 * doc.toObject(); // { name: 'Wreck-it Ralph' }
1405 *
1406 * With transformations we can do a lot more than remove properties. We can even return completely new customized objects:
1407 *
1408 * if (!schema.options.toObject) schema.options.toObject = {};
1409 * schema.options.toObject.transform = function (doc, ret, options) {
1410 * return { movie: ret.name }
1411 * }
1412 *
1413 * // without the transformation in the schema
1414 * doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
1415 *
1416 * // with the transformation
1417 * doc.toObject(); // { movie: 'Wreck-it Ralph' }
1418 *
1419 * _Note: if a transform function returns `undefined`, the return value will be ignored._
1420 *
1421 * Transformations may also be applied inline, overridding any transform set in the options:
1422 *
1423 * function xform (doc, ret, options) {
1424 * return { inline: ret.name, custom: true }
1425 * }
1426 *
1427 * // pass the transform as an inline option
1428 * doc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }
1429 *
1430 * _Note: if you call `toObject` and pass any options, the transform declared in your schema options will __not__ be applied. To force its application pass `transform: true`_
1431 *
1432 * if (!schema.options.toObject) schema.options.toObject = {};
1433 * schema.options.toObject.hide = '_id';
1434 * schema.options.toObject.transform = function (doc, ret, options) {
1435 * if (options.hide) {
1436 * options.hide.split(' ').forEach(function (prop) {
1437 * delete ret[prop];
1438 * });
1439 * }
1440 * }
1441 *
1442 * var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });
1443 * doc.toObject(); // { secret: 47, name: 'Wreck-it Ralph' }
1444 * doc.toObject({ hide: 'secret _id' }); // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }
1445 * doc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }
1446 *
1447 * Transforms are applied to the document _and each of its sub-documents_. To determine whether or not you are currently operating on a sub-document you might use the following guard:
1448 *
1449 * if ('function' == typeof doc.ownerDocument) {
1450 * // working with a sub doc
1451 * }
1452 *
1453 * Transforms, like all of these options, are also available for `toJSON`.
1454 *
1455 * See [schema options](/docs/guide.html#toObject) for some more details.
1456 *
1457 * _During save, no custom options are applied to the document before being sent to the database._
1458 *
1459 * @param {Object} [options]
1460 * @return {Object} js object
1461 * @see mongodb.Binary http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html
1462 * @api public
1463 */
1464
14651Document.prototype.toObject = function (options) {
14660 if (options && options.depopulate && this.$__.wasPopulated) {
1467 // populated paths that we set to a document
14680 return clone(this._id, options);
1469 }
1470
1471 // When internally saving this document we always pass options,
1472 // bypassing the custom schema options.
14730 if (!(options && 'Object' == options.constructor.name)) {
14740 options = this.schema.options.toObject
1475 ? clone(this.schema.options.toObject)
1476 : {};
1477 }
1478
14790 ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
1480
14810 var ret = clone(this._doc, options);
1482
14830 if (options.virtuals || options.getters && false !== options.virtuals) {
14840 applyGetters(this, ret, 'virtuals', options);
1485 }
1486
14870 if (options.getters) {
14880 applyGetters(this, ret, 'paths', options);
1489 // applyGetters for paths will add nested empty objects;
1490 // if minimize is set, we need to remove them.
14910 if (options.minimize) {
14920 ret = minimize(ret) || {};
1493 }
1494 }
1495
1496 // In the case where a subdocument has its own transform function, we need to
1497 // check and see if the parent has a transform (options.transform) and if the
1498 // child schema has a transform (this.schema.options.toObject) In this case,
1499 // we need to adjust options.transform to be the child schema's transform and
1500 // not the parent schema's
15010 if (true === options.transform ||
1502 (this.schema.options.toObject && options.transform)) {
15030 var opts = options.json
1504 ? this.schema.options.toJSON
1505 : this.schema.options.toObject;
15060 if (opts) {
15070 options.transform = opts.transform;
1508 }
1509 }
1510
15110 if ('function' == typeof options.transform) {
15120 var xformed = options.transform(this, ret, options);
15130 if ('undefined' != typeof xformed) ret = xformed;
1514 }
1515
15160 return ret;
1517};
1518
1519/*!
1520 * Minimizes an object, removing undefined values and empty objects
1521 *
1522 * @param {Object} object to minimize
1523 * @return {Object}
1524 */
1525
15261function minimize (obj) {
15270 var keys = Object.keys(obj)
1528 , i = keys.length
1529 , hasKeys
1530 , key
1531 , val
1532
15330 while (i--) {
15340 key = keys[i];
15350 val = obj[key];
1536
15370 if (utils.isObject(val)) {
15380 obj[key] = minimize(val);
1539 }
1540
15410 if (undefined === obj[key]) {
15420 delete obj[key];
15430 continue;
1544 }
1545
15460 hasKeys = true;
1547 }
1548
15490 return hasKeys
1550 ? obj
1551 : undefined;
1552}
1553
1554/*!
1555 * Applies virtuals properties to `json`.
1556 *
1557 * @param {Document} self
1558 * @param {Object} json
1559 * @param {String} type either `virtuals` or `paths`
1560 * @return {Object} `json`
1561 */
1562
15631function applyGetters (self, json, type, options) {
15640 var schema = self.schema
1565 , paths = Object.keys(schema[type])
1566 , i = paths.length
1567 , path
1568
15690 while (i--) {
15700 path = paths[i];
1571
15720 var parts = path.split('.')
1573 , plen = parts.length
1574 , last = plen - 1
1575 , branch = json
1576 , part
1577
15780 for (var ii = 0; ii < plen; ++ii) {
15790 part = parts[ii];
15800 if (ii === last) {
15810 branch[part] = clone(self.get(path), options);
1582 } else {
15830 branch = branch[part] || (branch[part] = {});
1584 }
1585 }
1586 }
1587
15880 return json;
1589}
1590
1591/**
1592 * The return value of this method is used in calls to JSON.stringify(doc).
1593 *
1594 * This method accepts the same options as [Document#toObject](#document_Document-toObject). To apply the options to every document of your schema by default, set your [schemas](#schema_Schema) `toJSON` option to the same argument.
1595 *
1596 * schema.set('toJSON', { virtuals: true })
1597 *
1598 * See [schema options](/docs/guide.html#toJSON) for details.
1599 *
1600 * @param {Object} options
1601 * @return {Object}
1602 * @see Document#toObject #document_Document-toObject
1603 * @api public
1604 */
1605
16061Document.prototype.toJSON = function (options) {
1607 // check for object type since an array of documents
1608 // being stringified passes array indexes instead
1609 // of options objects. JSON.stringify([doc, doc])
1610 // The second check here is to make sure that populated documents (or
1611 // subdocuments) use their own options for `.toJSON()` instead of their
1612 // parent's
16130 if (!(options && 'Object' == options.constructor.name)
1614 || ((!options || options.json) && this.schema.options.toJSON)) {
16150 options = this.schema.options.toJSON
1616 ? clone(this.schema.options.toJSON)
1617 : {};
1618 }
16190 options.json = true;
1620
16210 return this.toObject(options);
1622};
1623
1624/**
1625 * Helper for console.log
1626 *
1627 * @api public
1628 */
1629
16301Document.prototype.inspect = function (options) {
16310 var opts = options && 'Object' == options.constructor.name ? options :
1632 this.schema.options.toObject ? clone(this.schema.options.toObject) :
1633 {};
16340 opts.minimize = false;
16350 return inspect(this.toObject(opts));
1636};
1637
1638/**
1639 * Helper for console.log
1640 *
1641 * @api public
1642 * @method toString
1643 */
1644
16451Document.prototype.toString = Document.prototype.inspect;
1646
1647/**
1648 * Returns true if the Document stores the same data as doc.
1649 *
1650 * Documents are considered equal when they have matching `_id`s.
1651 *
1652 * @param {Document} doc a document to compare
1653 * @return {Boolean}
1654 * @api public
1655 */
1656
16571Document.prototype.equals = function (doc) {
16580 var tid = this.get('_id');
16590 var docid = doc.get('_id');
16600 return tid && tid.equals
1661 ? tid.equals(docid)
1662 : tid === docid;
1663}
1664
1665/**
1666 * Populates document references, executing the `callback` when complete.
1667 *
1668 * ####Example:
1669 *
1670 * doc
1671 * .populate('company')
1672 * .populate({
1673 * path: 'notes',
1674 * match: /airline/,
1675 * select: 'text',
1676 * model: 'modelName'
1677 * options: opts
1678 * }, function (err, user) {
1679 * assert(doc._id == user._id) // the document itself is passed
1680 * })
1681 *
1682 * // summary
1683 * doc.populate(path) // not executed
1684 * doc.populate(options); // not executed
1685 * doc.populate(path, callback) // executed
1686 * doc.populate(options, callback); // executed
1687 * doc.populate(callback); // executed
1688 *
1689 *
1690 * ####NOTE:
1691 *
1692 * Population does not occur unless a `callback` is passed.
1693 * Passing the same path a second time will overwrite the previous path options.
1694 * See [Model.populate()](#model_Model.populate) for explaination of options.
1695 *
1696 * @see Model.populate #model_Model.populate
1697 * @param {String|Object} [path] The path to populate or an options object
1698 * @param {Function} [callback] When passed, population is invoked
1699 * @api public
1700 * @return {Document} this
1701 */
1702
17031Document.prototype.populate = function populate () {
17040 if (0 === arguments.length) return this;
1705
17060 var pop = this.$__.populate || (this.$__.populate = {});
17070 var args = utils.args(arguments);
17080 var fn;
1709
17100 if ('function' == typeof args[args.length-1]) {
17110 fn = args.pop();
1712 }
1713
1714 // allow `doc.populate(callback)`
17150 if (args.length) {
1716 // use hash to remove duplicate paths
17170 var res = utils.populate.apply(null, args);
17180 for (var i = 0; i < res.length; ++i) {
17190 pop[res[i].path] = res[i];
1720 }
1721 }
1722
17230 if (fn) {
17240 var paths = utils.object.vals(pop);
17250 this.$__.populate = undefined;
17260 this.constructor.populate(this, paths, fn);
1727 }
1728
17290 return this;
1730}
1731
1732/**
1733 * Gets _id(s) used during population of the given `path`.
1734 *
1735 * ####Example:
1736 *
1737 * Model.findOne().populate('author').exec(function (err, doc) {
1738 * console.log(doc.author.name) // Dr.Seuss
1739 * console.log(doc.populated('author')) // '5144cf8050f071d979c118a7'
1740 * })
1741 *
1742 * If the path was not populated, undefined is returned.
1743 *
1744 * @param {String} path
1745 * @return {Array|ObjectId|Number|Buffer|String|undefined}
1746 * @api public
1747 */
1748
17491Document.prototype.populated = function (path, val, options) {
1750 // val and options are internal
1751
17520 if (null == val) {
17530 if (!this.$__.populated) return undefined;
17540 var v = this.$__.populated[path];
17550 if (v) return v.value;
17560 return undefined;
1757 }
1758
1759 // internal
1760
17610 if (true === val) {
17620 if (!this.$__.populated) return undefined;
17630 return this.$__.populated[path];
1764 }
1765
17660 this.$__.populated || (this.$__.populated = {});
17670 this.$__.populated[path] = { value: val, options: options };
17680 return val;
1769}
1770
1771/**
1772 * Returns the full path to this document.
1773 *
1774 * @param {String} [path]
1775 * @return {String}
1776 * @api private
1777 * @method $__fullPath
1778 * @memberOf Document
1779 */
1780
17811Document.prototype.$__fullPath = function (path) {
1782 // overridden in SubDocuments
17830 return path || '';
1784}
1785
1786/*!
1787 * Module exports.
1788 */
1789
17901Document.ValidationError = ValidationError;
17911module.exports = exports = Document;
1792

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js

100%
2
2
0
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var Binary = require('mongodb').BSONPure.Binary;
7
81module.exports = exports = Binary;
9

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js

15%
80
12
68
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var MongooseCollection = require('../../collection')
7 , Collection = require('mongodb').Collection
8 , STATES = require('../../connectionstate')
9 , utils = require('../../utils')
10
11/**
12 * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) collection implementation.
13 *
14 * All methods methods from the [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver are copied and wrapped in queue management.
15 *
16 * @inherits Collection
17 * @api private
18 */
19
201function NativeCollection () {
210 this.collection = null;
220 MongooseCollection.apply(this, arguments);
23}
24
25/*!
26 * Inherit from abstract Collection.
27 */
28
291NativeCollection.prototype.__proto__ = MongooseCollection.prototype;
30
31/**
32 * Called when the connection opens.
33 *
34 * @api private
35 */
36
371NativeCollection.prototype.onOpen = function () {
380 var self = this;
39
40 // always get a new collection in case the user changed host:port
41 // of parent db instance when re-opening the connection.
42
430 if (!self.opts.capped.size) {
44 // non-capped
450 return self.conn.db.collection(self.name, callback);
46 }
47
48 // capped
490 return self.conn.db.collection(self.name, function (err, c) {
500 if (err) return callback(err);
51
52 // discover if this collection exists and if it is capped
530 c.options(function (err, exists) {
540 if (err) return callback(err);
55
560 if (exists) {
570 if (exists.capped) {
580 callback(null, c);
59 } else {
600 var msg = 'A non-capped collection exists with the name: '+ self.name +'\n\n'
61 + ' To use this collection as a capped collection, please '
62 + 'first convert it.\n'
63 + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
640 err = new Error(msg);
650 callback(err);
66 }
67 } else {
68 // create
690 var opts = utils.clone(self.opts.capped);
700 opts.capped = true;
710 self.conn.db.createCollection(self.name, opts, callback);
72 }
73 });
74 });
75
760 function callback (err, collection) {
770 if (err) {
78 // likely a strict mode error
790 self.conn.emit('error', err);
80 } else {
810 self.collection = collection;
820 MongooseCollection.prototype.onOpen.call(self);
83 }
84 };
85};
86
87/**
88 * Called when the connection closes
89 *
90 * @api private
91 */
92
931NativeCollection.prototype.onClose = function () {
940 MongooseCollection.prototype.onClose.call(this);
95};
96
97/*!
98 * Copy the collection methods and make them subject to queues
99 */
100
1011for (var i in Collection.prototype) {
10230 (function(i){
10330 NativeCollection.prototype[i] = function () {
1040 if (this.buffer) {
1050 this.addQueue(i, arguments);
1060 return;
107 }
108
1090 var collection = this.collection
110 , args = arguments
111 , self = this
112 , debug = self.conn.base.options.debug;
113
1140 if (debug) {
1150 if ('function' === typeof debug) {
1160 debug.apply(debug
117 , [self.name, i].concat(utils.args(args, 0, args.length-1)));
118 } else {
1190 console.error('\x1B[0;36mMongoose:\x1B[0m %s.%s(%s) %s %s %s'
120 , self.name
121 , i
122 , print(args[0])
123 , print(args[1])
124 , print(args[2])
125 , print(args[3]))
126 }
127 }
128
1290 return collection[i].apply(collection, args);
130 };
131 })(i);
132}
133
134/*!
135 * Debug print helper
136 */
137
1381function print (arg) {
1390 var type = typeof arg;
1400 if ('function' === type || 'undefined' === type) return '';
1410 return format(arg);
142}
143
144/*!
145 * Debug print helper
146 */
147
1481function format (obj, sub) {
1490 var x = utils.clone(obj);
1500 if (x) {
1510 if ('Binary' === x.constructor.name) {
1520 x = '[object Buffer]';
1530 } else if ('ObjectID' === x.constructor.name) {
1540 var representation = 'ObjectId("' + x.toHexString() + '")';
1550 x = { inspect: function() { return representation; } };
1560 } else if ('Date' === x.constructor.name) {
1570 var representation = 'new Date("' + x.toUTCString() + '")';
1580 x = { inspect: function() { return representation; } };
1590 } else if ('Object' === x.constructor.name) {
1600 var keys = Object.keys(x)
161 , i = keys.length
162 , key
1630 while (i--) {
1640 key = keys[i];
1650 if (x[key]) {
1660 if ('Binary' === x[key].constructor.name) {
1670 x[key] = '[object Buffer]';
1680 } else if ('Object' === x[key].constructor.name) {
1690 x[key] = format(x[key], true);
1700 } else if ('ObjectID' === x[key].constructor.name) {
1710 ;(function(x){
1720 var representation = 'ObjectId("' + x[key].toHexString() + '")';
1730 x[key] = { inspect: function() { return representation; } };
174 })(x)
1750 } else if ('Date' === x[key].constructor.name) {
1760 ;(function(x){
1770 var representation = 'new Date("' + x[key].toUTCString() + '")';
1780 x[key] = { inspect: function() { return representation; } };
179 })(x)
1800 } else if (Array.isArray(x[key])) {
1810 x[key] = x[key].map(function (o) {
1820 return format(o, true)
183 });
184 }
185 }
186 }
187 }
1880 if (sub) return x;
189 }
190
1910 return require('util')
192 .inspect(x, false, 10, true)
193 .replace(/\n/g, '')
194 .replace(/\s{2,}/g, ' ')
195}
196
197/**
198 * Retreives information about this collections indexes.
199 *
200 * @param {Function} callback
201 * @method getIndexes
202 * @api public
203 */
204
2051NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;
206
207/*!
208 * Module exports.
209 */
210
2111module.exports = NativeCollection;
212

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js

25%
158
40
118
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var MongooseConnection = require('../../connection')
6 , mongo = require('mongodb')
7 , Db = mongo.Db
8 , Server = mongo.Server
9 , Mongos = mongo.Mongos
10 , STATES = require('../../connectionstate')
11 , ReplSetServers = mongo.ReplSetServers
12 , utils = require('../../utils');
13
14/**
15 * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) connection implementation.
16 *
17 * @inherits Connection
18 * @api private
19 */
20
211function NativeConnection() {
221 MongooseConnection.apply(this, arguments);
231 this._listening = false;
24};
25
26/**
27 * Expose the possible connection states.
28 * @api public
29 */
30
311NativeConnection.STATES = STATES;
32
33/*!
34 * Inherits from Connection.
35 */
36
371NativeConnection.prototype.__proto__ = MongooseConnection.prototype;
38
39/**
40 * Opens the connection to MongoDB.
41 *
42 * @param {Function} fn
43 * @return {Connection} this
44 * @api private
45 */
46
471NativeConnection.prototype.doOpen = function (fn) {
481 if (this.db) {
490 mute(this);
50 }
51
521 var server = new Server(this.host, this.port, this.options.server);
531 this.db = new Db(this.name, server, this.options.db);
54
551 var self = this;
561 this.db.open(function (err) {
570 if (err) return fn(err);
580 listen(self);
590 fn();
60 });
61
621 return this;
63};
64
65/**
66 * Switches to a different database using the same connection pool.
67 *
68 * Returns a new connection object, with the new db.
69 *
70 * @param {String} name The database name
71 * @return {Connection} New Connection Object
72 * @api public
73 */
74
751NativeConnection.prototype.useDb = function (name) {
76 // we have to manually copy all of the attributes...
770 var newConn = new this.constructor();
780 newConn.name = name;
790 newConn.base = this.base;
800 newConn.collections = {};
810 newConn.models = {};
820 newConn.replica = this.replica;
830 newConn.hosts = this.hosts;
840 newConn.host = this.host;
850 newConn.port = this.port;
860 newConn.user = this.user;
870 newConn.pass = this.pass;
880 newConn.options = this.options;
890 newConn._readyState = this._readyState;
900 newConn._closeCalled = this._closeCalled;
910 newConn._hasOpened = this._hasOpened;
920 newConn._listening = false;
93
94 // First, when we create another db object, we are not guaranteed to have a
95 // db object to work with. So, in the case where we have a db object and it
96 // is connected, we can just proceed with setting everything up. However, if
97 // we do not have a db or the state is not connected, then we need to wait on
98 // the 'open' event of the connection before doing the rest of the setup
99 // the 'connected' event is the first time we'll have access to the db object
100
1010 var self = this;
102
1030 if (this.db && this.db._state == 'connected') {
1040 wireup();
105 } else {
1060 this.once('connected', wireup);
107 }
108
1090 function wireup () {
1100 newConn.db = self.db.db(name);
1110 newConn.onOpen();
112 // setup the events appropriately
1130 listen(newConn);
114 }
115
1160 newConn.name = name;
117
118 // push onto the otherDbs stack, this is used when state changes
1190 this.otherDbs.push(newConn);
1200 newConn.otherDbs.push(this);
121
1220 return newConn;
123};
124
125/*!
126 * Register listeners for important events and bubble appropriately.
127 */
128
1291function listen (conn) {
1300 if (conn._listening) return;
1310 conn._listening = true;
132
1330 conn.db.on('close', function(){
1340 if (conn._closeCalled) return;
135
136 // the driver never emits an `open` event. auto_reconnect still
137 // emits a `close` event but since we never get another
138 // `open` we can't emit close
1390 if (conn.db.serverConfig.autoReconnect) {
1400 conn.readyState = STATES.disconnected;
1410 conn.emit('close');
1420 return;
143 }
1440 conn.onClose();
145 });
1460 conn.db.on('error', function(err){
1470 conn.emit('error', err);
148 });
1490 conn.db.on('timeout', function(err){
1500 var error = new Error(err && err.err || 'connection timeout');
1510 conn.emit('error', error);
152 });
1530 conn.db.on('open', function (err, db) {
1540 if (STATES.disconnected === conn.readyState && db && db.databaseName) {
1550 conn.readyState = STATES.connected;
1560 conn.emit('reconnected')
157 }
158 })
159}
160
161/*!
162 * Remove listeners registered in `listen`
163 */
164
1651function mute (conn) {
1660 if (!conn.db) throw new Error('missing db');
1670 conn.db.removeAllListeners("close");
1680 conn.db.removeAllListeners("error");
1690 conn.db.removeAllListeners("timeout");
1700 conn.db.removeAllListeners("open");
1710 conn.db.removeAllListeners("fullsetup");
1720 conn._listening = false;
173}
174
175/**
176 * Opens a connection to a MongoDB ReplicaSet.
177 *
178 * See description of [doOpen](#NativeConnection-doOpen) for server options. In this case `options.replset` is also passed to ReplSetServers.
179 *
180 * @param {Function} fn
181 * @api private
182 * @return {Connection} this
183 */
184
1851NativeConnection.prototype.doOpenSet = function (fn) {
1860 if (this.db) {
1870 mute(this);
188 }
189
1900 var servers = []
191 , self = this;
192
1930 this.hosts.forEach(function (server) {
1940 var host = server.host || server.ipc;
1950 var port = server.port || 27017;
1960 servers.push(new Server(host, port, self.options.server));
197 })
198
1990 var server = this.options.mongos
200 ? new Mongos(servers, this.options.mongos)
201 : new ReplSetServers(servers, this.options.replset);
2020 this.db = new Db(this.name, server, this.options.db);
203
2040 this.db.on('fullsetup', function () {
2050 self.emit('fullsetup')
206 });
207
2080 this.db.open(function (err) {
2090 if (err) return fn(err);
2100 fn();
2110 listen(self);
212 });
213
2140 return this;
215};
216
217/**
218 * Closes the connection
219 *
220 * @param {Function} fn
221 * @return {Connection} this
222 * @api private
223 */
224
2251NativeConnection.prototype.doClose = function (fn) {
2260 this.db.close();
2270 if (fn) fn();
2280 return this;
229}
230
231/**
232 * Prepares default connection options for the node-mongodb-native driver.
233 *
234 * _NOTE: `passed` options take precedence over connection string options._
235 *
236 * @param {Object} passed options that were passed directly during connection
237 * @param {Object} [connStrOptions] options that were passed in the connection string
238 * @api private
239 */
240
2411NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {
2421 var o = passed || {};
2431 o.db || (o.db = {});
2441 o.auth || (o.auth = {});
2451 o.server || (o.server = {});
2461 o.replset || (o.replset = {});
2471 o.server.socketOptions || (o.server.socketOptions = {});
2481 o.replset.socketOptions || (o.replset.socketOptions = {});
249
2501 var opts = connStrOpts || {};
2511 Object.keys(opts).forEach(function (name) {
2520 switch (name) {
253 case 'ssl':
254 case 'poolSize':
2550 if ('undefined' == typeof o.server[name]) {
2560 o.server[name] = o.replset[name] = opts[name];
257 }
2580 break;
259 case 'slaveOk':
2600 if ('undefined' == typeof o.server.slave_ok) {
2610 o.server.slave_ok = opts[name];
262 }
2630 break;
264 case 'autoReconnect':
2650 if ('undefined' == typeof o.server.auto_reconnect) {
2660 o.server.auto_reconnect = opts[name];
267 }
2680 break;
269 case 'socketTimeoutMS':
270 case 'connectTimeoutMS':
2710 if ('undefined' == typeof o.server.socketOptions[name]) {
2720 o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name];
273 }
2740 break;
275 case 'authdb':
2760 if ('undefined' == typeof o.auth.authdb) {
2770 o.auth.authdb = opts[name];
278 }
2790 break;
280 case 'authSource':
2810 if ('undefined' == typeof o.auth.authSource) {
2820 o.auth.authSource = opts[name];
283 }
2840 break;
285 case 'retries':
286 case 'reconnectWait':
287 case 'rs_name':
2880 if ('undefined' == typeof o.replset[name]) {
2890 o.replset[name] = opts[name];
290 }
2910 break;
292 case 'replicaSet':
2930 if ('undefined' == typeof o.replset.rs_name) {
2940 o.replset.rs_name = opts[name];
295 }
2960 break;
297 case 'readSecondary':
2980 if ('undefined' == typeof o.replset.read_secondary) {
2990 o.replset.read_secondary = opts[name];
300 }
3010 break;
302 case 'nativeParser':
3030 if ('undefined' == typeof o.db.native_parser) {
3040 o.db.native_parser = opts[name];
305 }
3060 break;
307 case 'w':
308 case 'safe':
309 case 'fsync':
310 case 'journal':
311 case 'wtimeoutMS':
3120 if ('undefined' == typeof o.db[name]) {
3130 o.db[name] = opts[name];
314 }
3150 break;
316 case 'readPreference':
3170 if ('undefined' == typeof o.db.read_preference) {
3180 o.db.read_preference = opts[name];
319 }
3200 break;
321 case 'readPreferenceTags':
3220 if ('undefined' == typeof o.db.read_preference_tags) {
3230 o.db.read_preference_tags = opts[name];
324 }
3250 break;
326 }
327 })
328
3291 if (!('auto_reconnect' in o.server)) {
3301 o.server.auto_reconnect = true;
331 }
332
3331 if (!o.db.read_preference) {
334 // read from primaries by default
3351 o.db.read_preference = 'primary';
336 }
337
338 // mongoose creates its own ObjectIds
3391 o.db.forceServerObjectId = false;
340
341 // default safe using new nomenclature
3421 if (!('journal' in o.db || 'j' in o.db ||
343 'fsync' in o.db || 'safe' in o.db || 'w' in o.db)) {
3441 o.db.w = 1;
345 }
346
3471 validate(o);
3481 return o;
349}
350
351/*!
352 * Validates the driver db options.
353 *
354 * @param {Object} o
355 */
356
3571function validate (o) {
3581 if (-1 === o.db.w || 0 === o.db.w) {
3590 if (o.db.journal || o.db.fsync || o.db.safe) {
3600 throw new Error(
361 'Invalid writeConcern: '
362 + 'w set to -1 or 0 cannot be combined with safe|fsync|journal');
363 }
364 }
365}
366
367/*!
368 * Module exports.
369 */
370
3711module.exports = NativeConnection;
372

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js

100%
2
2
0
LineHitsSource
1
2/*!
3 * [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) ObjectId
4 * @constructor NodeMongoDbObjectId
5 * @see ObjectId
6 */
7
81var ObjectId = require('mongodb').BSONPure.ObjectID;
9
10/*!
11 * ignore
12 */
13
141module.exports = exports = ObjectId;
15
16

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/error.js

68%
19
13
6
LineHitsSource
1
2/**
3 * MongooseError constructor
4 *
5 * @param {String} msg Error message
6 * @inherits Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error
7 */
8
91function MongooseError (msg) {
100 Error.call(this);
110 Error.captureStackTrace(this, arguments.callee);
120 this.message = msg;
130 this.name = 'MongooseError';
14};
15
16/*!
17 * Formats error messages
18 */
19
201MongooseError.prototype.formatMessage = function (msg, path, type, val) {
210 if (!msg) throw new TypeError('message is required');
22
230 return msg.replace(/{PATH}/, path)
24 .replace(/{VALUE}/, String(val||''))
25 .replace(/{TYPE}/, type || 'declared type');
26}
27
28/*!
29 * Inherits from Error.
30 */
31
321MongooseError.prototype.__proto__ = Error.prototype;
33
34/*!
35 * Module exports.
36 */
37
381module.exports = exports = MongooseError;
39
40/**
41 * The default built-in validator error messages.
42 *
43 * @see Error.messages #error_messages_MongooseError-messages
44 * @api public
45 */
46
471MongooseError.messages = require('./error/messages');
48
49// backward compat
501MongooseError.Messages = MongooseError.messages;
51
52/*!
53 * Expose subclasses
54 */
55
561MongooseError.CastError = require('./error/cast');
571MongooseError.ValidationError = require('./error/validation')
581MongooseError.ValidatorError = require('./error/validator')
591MongooseError.VersionError =require('./error/version')
601MongooseError.OverwriteModelError = require('./error/overwriteModel')
611MongooseError.MissingSchemaError = require('./error/missingSchema')
621MongooseError.DivergentArrayError = require('./error/divergentArray')
63
64

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/error/cast.js

40%
10
4
6
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var MongooseError = require('../error.js');
6
7/**
8 * Casting Error constructor.
9 *
10 * @param {String} type
11 * @param {String} value
12 * @inherits MongooseError
13 * @api private
14 */
15
161function CastError (type, value, path) {
170 MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '" at path "' + path + '"');
180 Error.captureStackTrace(this, arguments.callee);
190 this.name = 'CastError';
200 this.type = type;
210 this.value = value;
220 this.path = path;
23};
24
25/*!
26 * Inherits from MongooseError.
27 */
28
291CastError.prototype.__proto__ = MongooseError.prototype;
30
31/*!
32 * exports
33 */
34
351module.exports = CastError;
36

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/error/divergentArray.js

50%
8
4
4
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var MongooseError = require('../error.js');
7
8/*!
9 * DivergentArrayError constructor.
10 *
11 * @inherits MongooseError
12 */
13
141function DivergentArrayError (paths) {
150 var msg = 'For your own good, using `document.save()` to update an array '
16 + 'which was selected using an $elemMatch projection OR '
17 + 'populated using skip, limit, query conditions, or exclusion of '
18 + 'the _id field when the operation results in a $pop or $set of '
19 + 'the entire array is not supported. The following '
20 + 'path(s) would have been modified unsafely:\n'
21 + ' ' + paths.join('\n ') + '\n'
22 + 'Use Model.update() to update these arrays instead.'
23 // TODO write up a docs page (FAQ) and link to it
24
250 MongooseError.call(this, msg);
260 Error.captureStackTrace(this, arguments.callee);
270 this.name = 'DivergentArrayError';
28};
29
30/*!
31 * Inherits from MongooseError.
32 */
33
341DivergentArrayError.prototype.__proto__ = MongooseError.prototype;
35
36/*!
37 * exports
38 */
39
401module.exports = DivergentArrayError;
41

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/error/messages.js

100%
10
10
0
LineHitsSource
1
2/**
3 * The default built-in validator error messages. These may be customized.
4 *
5 * // customize within each schema or globally like so
6 * var mongoose = require('mongoose');
7 * mongoose.Error.messages.String.enum = "Your custom message for {PATH}.";
8 *
9 * As you might have noticed, error messages support basic templating
10 *
11 * - `{PATH}` is replaced with the invalid document path
12 * - `{VALUE}` is replaced with the invalid value
13 * - `{TYPE}` is replaced with the validator type such as "regexp", "min", or "user defined"
14 * - `{MIN}` is replaced with the declared min value for the Number.min validator
15 * - `{MAX}` is replaced with the declared max value for the Number.max validator
16 *
17 * Click the "show code" link below to see all defaults.
18 *
19 * @property messages
20 * @receiver MongooseError
21 * @api public
22 */
23
241var msg = module.exports = exports = {};
25
261msg.general = {};
271msg.general.default = "Validator failed for path `{PATH}` with value `{VALUE}`";
281msg.general.required = "Path `{PATH}` is required.";
29
301msg.Number = {};
311msg.Number.min = "Path `{PATH}` ({VALUE}) is less than minimum allowed value ({MIN}).";
321msg.Number.max = "Path `{PATH}` ({VALUE}) is more than maximum allowed value ({MAX}).";
33
341msg.String = {};
351msg.String.enum = "`{VALUE}` is not a valid enum value for path `{PATH}`.";
361msg.String.match = "Path `{PATH}` is invalid ({VALUE}).";
37
38

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/error/missingSchema.js

50%
8
4
4
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var MongooseError = require('../error.js');
7
8/*!
9 * MissingSchema Error constructor.
10 *
11 * @inherits MongooseError
12 */
13
141function MissingSchemaError (name) {
150 var msg = 'Schema hasn\'t been registered for model "' + name + '".\n'
16 + 'Use mongoose.model(name, schema)';
170 MongooseError.call(this, msg);
180 Error.captureStackTrace(this, arguments.callee);
190 this.name = 'MissingSchemaError';
20};
21
22/*!
23 * Inherits from MongooseError.
24 */
25
261MissingSchemaError.prototype.__proto__ = MongooseError.prototype;
27
28/*!
29 * exports
30 */
31
321module.exports = MissingSchemaError;
33

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/error/overwriteModel.js

57%
7
4
3
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var MongooseError = require('../error.js');
7
8/*!
9 * OverwriteModel Error constructor.
10 *
11 * @inherits MongooseError
12 */
13
141function OverwriteModelError (name) {
150 MongooseError.call(this, 'Cannot overwrite `' + name + '` model once compiled.');
160 Error.captureStackTrace(this, arguments.callee);
170 this.name = 'OverwriteModelError';
18};
19
20/*!
21 * Inherits from MongooseError.
22 */
23
241OverwriteModelError.prototype.__proto__ = MongooseError.prototype;
25
26/*!
27 * exports
28 */
29
301module.exports = OverwriteModelError;
31

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/error/validation.js

33%
15
5
10
LineHitsSource
1
2/*!
3 * Module requirements
4 */
5
61var MongooseError = require('../error.js')
7
8/**
9 * Document Validation Error
10 *
11 * @api private
12 * @param {Document} instance
13 * @inherits MongooseError
14 */
15
161function ValidationError (instance) {
170 MongooseError.call(this, "Validation failed");
180 Error.captureStackTrace(this, arguments.callee);
190 this.name = 'ValidationError';
200 this.errors = instance.errors = {};
21};
22
23/**
24 * Console.log helper
25 */
26
271ValidationError.prototype.toString = function () {
280 var ret = this.name + ': ';
290 var msgs = [];
30
310 Object.keys(this.errors).forEach(function (key) {
320 if (this == this.errors[key]) return;
330 msgs.push(String(this.errors[key]));
34 }, this)
35
360 return ret + msgs.join(', ');
37};
38
39/*!
40 * Inherits from MongooseError.
41 */
42
431ValidationError.prototype.__proto__ = MongooseError.prototype;
44
45/*!
46 * Module exports
47 */
48
491module.exports = exports = ValidationError;
50

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/error/validator.js

40%
15
6
9
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var MongooseError = require('../error.js');
61var errorMessages = MongooseError.messages;
7
8/**
9 * Schema validator error
10 *
11 * @param {String} path
12 * @param {String} msg
13 * @param {String|Number|any} val
14 * @inherits MongooseError
15 * @api private
16 */
17
181function ValidatorError (path, msg, type, val) {
190 if (!msg) msg = errorMessages.general.default;
200 var message = this.formatMessage(msg, path, type, val);
210 MongooseError.call(this, message);
220 Error.captureStackTrace(this, arguments.callee);
230 this.name = 'ValidatorError';
240 this.path = path;
250 this.type = type;
260 this.value = val;
27};
28
29/*!
30 * toString helper
31 */
32
331ValidatorError.prototype.toString = function () {
340 return this.message;
35}
36
37/*!
38 * Inherits from MongooseError
39 */
40
411ValidatorError.prototype.__proto__ = MongooseError.prototype;
42
43/*!
44 * exports
45 */
46
471module.exports = ValidatorError;
48

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/error/version.js

57%
7
4
3
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var MongooseError = require('../error.js');
7
8/**
9 * Version Error constructor.
10 *
11 * @inherits MongooseError
12 * @api private
13 */
14
151function VersionError () {
160 MongooseError.call(this, 'No matching document found.');
170 Error.captureStackTrace(this, arguments.callee);
180 this.name = 'VersionError';
19};
20
21/*!
22 * Inherits from MongooseError.
23 */
24
251VersionError.prototype.__proto__ = MongooseError.prototype;
26
27/*!
28 * exports
29 */
30
311module.exports = VersionError;
32

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/index.js

38%
133
51
82
LineHitsSource
11'use strict';
2
3/*!
4 * Module dependencies.
5 */
6
71var Schema = require('./schema')
8 , SchemaType = require('./schematype')
9 , VirtualType = require('./virtualtype')
10 , SchemaDefaults = require('./schemadefault')
11 , STATES = require('./connectionstate')
12 , Types = require('./types')
13 , Query = require('./query')
14 , Promise = require('./promise')
15 , Model = require('./model')
16 , Document = require('./document')
17 , utils = require('./utils')
18 , format = utils.toCollectionName
19 , mongodb = require('mongodb')
20 , pkg = require('../package.json')
21
22/*!
23 * Warn users if they are running an unstable release.
24 *
25 * Disable the warning by setting the MONGOOSE_DISABLE_STABILITY_WARNING
26 * environment variable.
27 */
28
291if (pkg.publishConfig && 'unstable' == pkg.publishConfig.tag) {
300 if (!process.env.MONGOOSE_DISABLE_STABILITY_WARNING) {
310 console.log('\u001b[33m');
320 console.log('##############################################################');
330 console.log('#');
340 console.log('# !!! MONGOOSE WARNING !!!');
350 console.log('#');
360 console.log('# This is an UNSTABLE release of Mongoose.');
370 console.log('# Unstable releases are available for preview/testing only.');
380 console.log('# DO NOT run this in production.');
390 console.log('#');
400 console.log('##############################################################');
410 console.log('\u001b[0m');
42 }
43}
44
45/**
46 * Mongoose constructor.
47 *
48 * The exports object of the `mongoose` module is an instance of this class.
49 * Most apps will only use this one instance.
50 *
51 * @api public
52 */
53
541function Mongoose () {
551 this.connections = [];
561 this.plugins = [];
571 this.models = {};
581 this.modelSchemas = {};
59 // default global options
601 this.options = {
61 pluralization: true
62 };
631 this.createConnection(); // default connection
64};
65
66/**
67 * Expose connection states for user-land
68 *
69 */
701Mongoose.prototype.STATES = STATES;
71
72/**
73 * Sets mongoose options
74 *
75 * ####Example:
76 *
77 * mongoose.set('test', value) // sets the 'test' option to `value`
78 *
79 * mongoose.set('debug', true) // enable logging collection methods + arguments to the console
80 *
81 * @param {String} key
82 * @param {String} value
83 * @api public
84 */
85
861Mongoose.prototype.set = function (key, value) {
870 if (arguments.length == 1) {
880 return this.options[key];
89 }
90
910 this.options[key] = value;
920 return this;
93};
94
95/**
96 * Gets mongoose options
97 *
98 * ####Example:
99 *
100 * mongoose.get('test') // returns the 'test' value
101 *
102 * @param {String} key
103 * @method get
104 * @api public
105 */
106
1071Mongoose.prototype.get = Mongoose.prototype.set;
108
109/*!
110 * ReplSet connection string check.
111 */
112
1131var rgxReplSet = /^.+,.+$/;
114
115/**
116 * Creates a Connection instance.
117 *
118 * Each `connection` instance maps to a single database. This method is helpful when mangaging multiple db connections.
119 *
120 * If arguments are passed, they are proxied to either [Connection#open](#connection_Connection-open) or [Connection#openSet](#connection_Connection-openSet) appropriately. This means we can pass `db`, `server`, and `replset` options to the driver. _Note that the `safe` option specified in your schema will overwrite the `safe` db option specified here unless you set your schemas `safe` option to `undefined`. See [this](/docs/guide.html#safe) for more information._
121 *
122 * _Options passed take precedence over options included in connection strings._
123 *
124 * ####Example:
125 *
126 * // with mongodb:// URI
127 * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
128 *
129 * // and options
130 * var opts = { db: { native_parser: true }}
131 * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
132 *
133 * // replica sets
134 * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
135 *
136 * // and options
137 * var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
138 * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
139 *
140 * // with [host, database_name[, port] signature
141 * db = mongoose.createConnection('localhost', 'database', port)
142 *
143 * // and options
144 * var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
145 * db = mongoose.createConnection('localhost', 'database', port, opts)
146 *
147 * // initialize now, connect later
148 * db = mongoose.createConnection();
149 * db.open('localhost', 'database', port, [opts]);
150 *
151 * @param {String} [uri] a mongodb:// URI
152 * @param {Object} [options] options to pass to the driver
153 * @see Connection#open #connection_Connection-open
154 * @see Connection#openSet #connection_Connection-openSet
155 * @return {Connection} the created Connection object
156 * @api public
157 */
158
1591Mongoose.prototype.createConnection = function () {
1601 var conn = new Connection(this);
1611 this.connections.push(conn);
162
1631 if (arguments.length) {
1640 if (rgxReplSet.test(arguments[0])) {
1650 conn.openSet.apply(conn, arguments);
166 } else {
1670 conn.open.apply(conn, arguments);
168 }
169 }
170
1711 return conn;
172};
173
174/**
175 * Opens the default mongoose connection.
176 *
177 * If arguments are passed, they are proxied to either [Connection#open](#connection_Connection-open) or [Connection#openSet](#connection_Connection-openSet) appropriately.
178 *
179 * _Options passed take precedence over options included in connection strings._
180 *
181 * ####Example:
182 *
183 * mongoose.connect('mongodb://user:pass@localhost:port/database');
184 *
185 * // replica sets
186 * var uri = 'mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port';
187 * mongoose.connect(uri);
188 *
189 * // with options
190 * mongoose.connect(uri, options);
191 *
192 * // connecting to multiple mongos
193 * var uri = 'mongodb://hostA:27501,hostB:27501';
194 * var opts = { mongos: true };
195 * mongoose.connect(uri, opts);
196 *
197 * @param {String} uri(s)
198 * @param {Object} [options]
199 * @param {Function} [callback]
200 * @see Mongoose#createConnection #index_Mongoose-createConnection
201 * @api public
202 * @return {Mongoose} this
203 */
204
2051Mongoose.prototype.connect = function () {
2061 var conn = this.connection;
207
2081 if (rgxReplSet.test(arguments[0])) {
2090 conn.openSet.apply(conn, arguments);
210 } else {
2111 conn.open.apply(conn, arguments);
212 }
213
2141 return this;
215};
216
217/**
218 * Disconnects all connections.
219 *
220 * @param {Function} [fn] called after all connection close.
221 * @return {Mongoose} this
222 * @api public
223 */
224
2251Mongoose.prototype.disconnect = function (fn) {
2260 var count = this.connections.length
227 , error
228
2290 this.connections.forEach(function(conn){
2300 conn.close(function(err){
2310 if (error) return;
232
2330 if (err) {
2340 error = err;
2350 if (fn) return fn(err);
2360 throw err;
237 }
238
2390 if (fn)
2400 --count || fn();
241 });
242 });
2430 return this;
244};
245
246/**
247 * Defines a model or retrieves it.
248 *
249 * Models defined on the `mongoose` instance are available to all connection created by the same `mongoose` instance.
250 *
251 * ####Example:
252 *
253 * var mongoose = require('mongoose');
254 *
255 * // define an Actor model with this mongoose instance
256 * mongoose.model('Actor', new Schema({ name: String }));
257 *
258 * // create a new connection
259 * var conn = mongoose.createConnection(..);
260 *
261 * // retrieve the Actor model
262 * var Actor = conn.model('Actor');
263 *
264 * _When no `collection` argument is passed, Mongoose produces a collection name by passing the model `name` to the [utils.toCollectionName](#utils_exports.toCollectionName) method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option._
265 *
266 * ####Example:
267 *
268 * var schema = new Schema({ name: String }, { collection: 'actor' });
269 *
270 * // or
271 *
272 * schema.set('collection', 'actor');
273 *
274 * // or
275 *
276 * var collectionName = 'actor'
277 * var M = mongoose.model('Actor', schema, collectionName)
278 *
279 * @param {String} name model name
280 * @param {Schema} [schema]
281 * @param {String} [collection] name (optional, induced from model name)
282 * @param {Boolean} [skipInit] whether to skip initialization (defaults to false)
283 * @api public
284 */
285
2861Mongoose.prototype.model = function (name, schema, collection, skipInit) {
2870 if ('string' == typeof schema) {
2880 collection = schema;
2890 schema = false;
290 }
291
2920 if (utils.isObject(schema) && !(schema instanceof Schema)) {
2930 schema = new Schema(schema);
294 }
295
2960 if ('boolean' === typeof collection) {
2970 skipInit = collection;
2980 collection = null;
299 }
300
301 // handle internal options from connection.model()
3020 var options;
3030 if (skipInit && utils.isObject(skipInit)) {
3040 options = skipInit;
3050 skipInit = true;
306 } else {
3070 options = {};
308 }
309
310 // look up schema for the collection. this might be a
311 // default schema like system.indexes stored in SchemaDefaults.
3120 if (!this.modelSchemas[name]) {
3130 if (!schema && name in SchemaDefaults) {
3140 schema = SchemaDefaults[name];
315 }
316
3170 if (schema) {
318 // cache it so we only apply plugins once
3190 this.modelSchemas[name] = schema;
3200 this._applyPlugins(schema);
321 } else {
3220 throw new mongoose.Error.MissingSchemaError(name);
323 }
324 }
325
3260 var model;
3270 var sub;
328
329 // connection.model() may be passing a different schema for
330 // an existing model name. in this case don't read from cache.
3310 if (this.models[name] && false !== options.cache) {
3320 if (schema instanceof Schema && schema != this.models[name].schema) {
3330 throw new mongoose.Error.OverwriteModelError(name);
334 }
335
3360 if (collection) {
337 // subclass current model with alternate collection
3380 model = this.models[name];
3390 schema = model.prototype.schema;
3400 sub = model.__subclass(this.connection, schema, collection);
341 // do not cache the sub model
3420 return sub;
343 }
344
3450 return this.models[name];
346 }
347
348 // ensure a schema exists
3490 if (!schema) {
3500 schema = this.modelSchemas[name];
3510 if (!schema) {
3520 throw new mongoose.Error.MissingSchemaError(name);
353 }
354 }
355
356 // Apply relevant "global" options to the schema
3570 if (!('pluralization' in schema.options)) schema.options.pluralization = this.options.pluralization;
358
359
3600 if (!collection) {
3610 collection = schema.get('collection') || format(name, schema.options);
362 }
363
3640 var connection = options.connection || this.connection;
3650 model = Model.compile(name, schema, collection, connection, this);
366
3670 if (!skipInit) {
3680 model.init();
369 }
370
3710 if (false === options.cache) {
3720 return model;
373 }
374
3750 return this.models[name] = model;
376}
377
378/**
379 * Returns an array of model names created on this instance of Mongoose.
380 *
381 * ####Note:
382 *
383 * _Does not include names of models created using `connection.model()`._
384 *
385 * @api public
386 * @return {Array}
387 */
388
3891Mongoose.prototype.modelNames = function () {
3900 var names = Object.keys(this.models);
3910 return names;
392}
393
394/**
395 * Applies global plugins to `schema`.
396 *
397 * @param {Schema} schema
398 * @api private
399 */
400
4011Mongoose.prototype._applyPlugins = function (schema) {
4020 for (var i = 0, l = this.plugins.length; i < l; i++) {
4030 schema.plugin(this.plugins[i][0], this.plugins[i][1]);
404 }
405}
406
407/**
408 * Declares a global plugin executed on all Schemas.
409 *
410 * Equivalent to calling `.plugin(fn)` on each Schema you create.
411 *
412 * @param {Function} fn plugin callback
413 * @param {Object} [opts] optional options
414 * @return {Mongoose} this
415 * @see plugins ./plugins.html
416 * @api public
417 */
418
4191Mongoose.prototype.plugin = function (fn, opts) {
4200 this.plugins.push([fn, opts]);
4210 return this;
422};
423
424/**
425 * The default connection of the mongoose module.
426 *
427 * ####Example:
428 *
429 * var mongoose = require('mongoose');
430 * mongoose.connect(...);
431 * mongoose.connection.on('error', cb);
432 *
433 * This is the connection used by default for every model created using [mongoose.model](#index_Mongoose-model).
434 *
435 * @property connection
436 * @return {Connection}
437 * @api public
438 */
439
4401Mongoose.prototype.__defineGetter__('connection', function(){
4413 return this.connections[0];
442});
443
444/*!
445 * Driver depentend APIs
446 */
447
4481var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';
449
450/*!
451 * Connection
452 */
453
4541var Connection = require(driver + '/connection');
455
456/*!
457 * Collection
458 */
459
4601var Collection = require(driver + '/collection');
461
462/**
463 * The Mongoose Collection constructor
464 *
465 * @method Collection
466 * @api public
467 */
468
4691Mongoose.prototype.Collection = Collection;
470
471/**
472 * The Mongoose [Connection](#connection_Connection) constructor
473 *
474 * @method Connection
475 * @api public
476 */
477
4781Mongoose.prototype.Connection = Connection;
479
480/**
481 * The Mongoose version
482 *
483 * @property version
484 * @api public
485 */
486
4871Mongoose.prototype.version = pkg.version;
488
489/**
490 * The Mongoose constructor
491 *
492 * The exports of the mongoose module is an instance of this class.
493 *
494 * ####Example:
495 *
496 * var mongoose = require('mongoose');
497 * var mongoose2 = new mongoose.Mongoose();
498 *
499 * @method Mongoose
500 * @api public
501 */
502
5031Mongoose.prototype.Mongoose = Mongoose;
504
505/**
506 * The Mongoose [Schema](#schema_Schema) constructor
507 *
508 * ####Example:
509 *
510 * var mongoose = require('mongoose');
511 * var Schema = mongoose.Schema;
512 * var CatSchema = new Schema(..);
513 *
514 * @method Schema
515 * @api public
516 */
517
5181Mongoose.prototype.Schema = Schema;
519
520/**
521 * The Mongoose [SchemaType](#schematype_SchemaType) constructor
522 *
523 * @method SchemaType
524 * @api public
525 */
526
5271Mongoose.prototype.SchemaType = SchemaType;
528
529/**
530 * The various Mongoose SchemaTypes.
531 *
532 * ####Note:
533 *
534 * _Alias of mongoose.Schema.Types for backwards compatibility._
535 *
536 * @property SchemaTypes
537 * @see Schema.SchemaTypes #schema_Schema.Types
538 * @api public
539 */
540
5411Mongoose.prototype.SchemaTypes = Schema.Types;
542
543/**
544 * The Mongoose [VirtualType](#virtualtype_VirtualType) constructor
545 *
546 * @method VirtualType
547 * @api public
548 */
549
5501Mongoose.prototype.VirtualType = VirtualType;
551
552/**
553 * The various Mongoose Types.
554 *
555 * ####Example:
556 *
557 * var mongoose = require('mongoose');
558 * var array = mongoose.Types.Array;
559 *
560 * ####Types:
561 *
562 * - [ObjectId](#types-objectid-js)
563 * - [Buffer](#types-buffer-js)
564 * - [SubDocument](#types-embedded-js)
565 * - [Array](#types-array-js)
566 * - [DocumentArray](#types-documentarray-js)
567 *
568 * Using this exposed access to the `ObjectId` type, we can construct ids on demand.
569 *
570 * var ObjectId = mongoose.Types.ObjectId;
571 * var id1 = new ObjectId;
572 *
573 * @property Types
574 * @api public
575 */
576
5771Mongoose.prototype.Types = Types;
578
579/**
580 * The Mongoose [Query](#query_Query) constructor.
581 *
582 * @method Query
583 * @api public
584 */
585
5861Mongoose.prototype.Query = Query;
587
588/**
589 * The Mongoose [Promise](#promise_Promise) constructor.
590 *
591 * @method Promise
592 * @api public
593 */
594
5951Mongoose.prototype.Promise = Promise;
596
597/**
598 * The Mongoose [Model](#model_Model) constructor.
599 *
600 * @method Model
601 * @api public
602 */
603
6041Mongoose.prototype.Model = Model;
605
606/**
607 * The Mongoose [Document](#document-js) constructor.
608 *
609 * @method Document
610 * @api public
611 */
612
6131Mongoose.prototype.Document = Document;
614
615/**
616 * The [MongooseError](#error_MongooseError) constructor.
617 *
618 * @method Error
619 * @api public
620 */
621
6221Mongoose.prototype.Error = require('./error');
623
624/**
625 * The [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver Mongoose uses.
626 *
627 * @property mongo
628 * @api public
629 */
630
6311Mongoose.prototype.mongo = require('mongodb');
632
633/**
634 * The [mquery](https://github.com/aheckmann/mquery) query builder Mongoose uses.
635 *
636 * @property mquery
637 * @api public
638 */
639
6401Mongoose.prototype.mquery = require('mquery');
641
642/*!
643 * The exports object is an instance of Mongoose.
644 *
645 * @api public
646 */
647
6481var mongoose = module.exports = exports = new Mongoose;
649

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/internal.js

18%
22
4
18
LineHitsSource
1/*!
2 * Dependencies
3 */
4
51var StateMachine = require('./statemachine')
61var ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')
7
81module.exports = exports = InternalCache;
9
101function InternalCache () {
110 this.strictMode = undefined;
120 this.selected = undefined;
130 this.shardval = undefined;
140 this.saveError = undefined;
150 this.validationError = undefined;
160 this.adhocPaths = undefined;
170 this.removing = undefined;
180 this.inserting = undefined;
190 this.version = undefined;
200 this.getters = {};
210 this._id = undefined;
220 this.populate = undefined; // what we want to populate in this doc
230 this.populated = undefined;// the _ids that have been populated
240 this.wasPopulated = false; // if this doc was the result of a population
250 this.scope = undefined;
260 this.activePaths = new ActiveRoster;
27
28 // embedded docs
290 this.ownerDocument = undefined;
300 this.fullPath = undefined;
31}
32

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/model.js

7%
731
58
673
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var Document = require('./document')
6 , MongooseArray = require('./types/array')
7 , MongooseBuffer = require('./types/buffer')
8 , MongooseError = require('./error')
9 , VersionError = MongooseError.VersionError
10 , DivergentArrayError = MongooseError.DivergentArrayError
11 , Query = require('./query')
12 , Aggregate = require('./aggregate')
13 , Schema = require('./schema')
14 , Types = require('./schema/index')
15 , utils = require('./utils')
16 , hasOwnProperty = utils.object.hasOwnProperty
17 , isMongooseObject = utils.isMongooseObject
18 , EventEmitter = require('events').EventEmitter
19 , merge = utils.merge
20 , Promise = require('./promise')
21 , assert = require('assert')
22 , util = require('util')
23 , tick = utils.tick
24 , Query = require('./query.js')
25
261var VERSION_WHERE = 1
27 , VERSION_INC = 2
28 , VERSION_ALL = VERSION_WHERE | VERSION_INC;
29
30/**
31 * Model constructor
32 *
33 * Provides the interface to MongoDB collections as well as creates document instances.
34 *
35 * @param {Object} doc values with which to create the document
36 * @inherits Document
37 * @event `error`: If listening to this event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model.
38 * @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event.
39 * @api public
40 */
41
421function Model (doc, fields, skipId) {
430 Document.call(this, doc, fields, skipId);
44};
45
46/*!
47 * Inherits from Document.
48 *
49 * All Model.prototype features are available on
50 * top level (non-sub) documents.
51 */
52
531Model.prototype.__proto__ = Document.prototype;
54
55/**
56 * Connection the model uses.
57 *
58 * @api public
59 * @property db
60 */
61
621Model.prototype.db;
63
64/**
65 * Collection the model uses.
66 *
67 * @api public
68 * @property collection
69 */
70
711Model.prototype.collection;
72
73/**
74 * The name of the model
75 *
76 * @api public
77 * @property modelName
78 */
79
801Model.prototype.modelName;
81
82/*!
83 * Handles doc.save() callbacks
84 */
85
861function handleSave (promise, self) {
870 return tick(function handleSave (err, result) {
880 if (err) {
89 // If the initial insert fails provide a second chance.
90 // (If we did this all the time we would break updates)
910 if (self.$__.inserting) {
920 self.isNew = true;
930 self.emit('isNew', true);
94 }
950 promise.error(err);
960 promise = self = null;
970 return;
98 }
99
1000 self.$__storeShard();
101
1020 var numAffected;
1030 if (result) {
104 // when inserting, the array of created docs is returned
1050 numAffected = result.length
106 ? result.length
107 : result;
108 } else {
1090 numAffected = 0;
110 }
111
112 // was this an update that required a version bump?
1130 if (self.$__.version && !self.$__.inserting) {
1140 var doIncrement = VERSION_INC === (VERSION_INC & self.$__.version);
1150 self.$__.version = undefined;
116
117 // increment version if was successful
1180 if (numAffected > 0) {
1190 if (doIncrement) {
1200 var key = self.schema.options.versionKey;
1210 var version = self.getValue(key) | 0;
1220 self.setValue(key, version + 1);
123 }
124 } else {
125 // the update failed. pass an error back
1260 promise.error(new VersionError);
1270 promise = self = null;
1280 return;
129 }
130 }
131
1320 self.emit('save', self, numAffected);
1330 promise.complete(self, numAffected);
1340 promise = self = null;
135 });
136}
137
138/**
139 * Saves this document.
140 *
141 * ####Example:
142 *
143 * product.sold = Date.now();
144 * product.save(function (err, product, numberAffected) {
145 * if (err) ..
146 * })
147 *
148 * The callback will receive three parameters, `err` if an error occurred, `product` which is the saved `product`, and `numberAffected` which will be 1 when the document was found and updated in the database, otherwise 0.
149 *
150 * The `fn` callback is optional. If no `fn` is passed and validation fails, the validation error will be emitted on the connection used to create this model.
151 *
152 * var db = mongoose.createConnection(..);
153 * var schema = new Schema(..);
154 * var Product = db.model('Product', schema);
155 *
156 * db.on('error', handleError);
157 *
158 * However, if you desire more local error handling you can add an `error` listener to the model and handle errors there instead.
159 *
160 * Product.on('error', handleError);
161 *
162 * @param {Function} [fn] optional callback
163 * @api public
164 * @see middleware http://mongoosejs.com/docs/middleware.html
165 */
166
1671Model.prototype.save = function save (fn) {
1680 var promise = new Promise(fn)
169 , complete = handleSave(promise, this)
170 , options = {}
171
1720 if (this.schema.options.safe) {
1730 options.safe = this.schema.options.safe;
174 }
175
1760 if (this.isNew) {
177 // send entire doc
1780 var obj = this.toObject({ depopulate: 1 });
179
1800 if (!utils.object.hasOwnProperty(obj || {}, '_id')) {
181 // documents must have an _id else mongoose won't know
182 // what to update later if more changes are made. the user
183 // wouldn't know what _id was generated by mongodb either
184 // nor would the ObjectId generated my mongodb necessarily
185 // match the schema definition.
1860 return complete(new Error('document must have an _id before saving'));
187 }
188
1890 this.$__version(true, obj);
1900 this.collection.insert(obj, options, complete);
1910 this.$__reset();
1920 this.isNew = false;
1930 this.emit('isNew', false);
194 // Make it possible to retry the insert
1950 this.$__.inserting = true;
196
197 } else {
198 // Make sure we don't treat it as a new object on error,
199 // since it already exists
2000 this.$__.inserting = false;
201
2020 var delta = this.$__delta();
203
2040 if (delta) {
2050 if (delta instanceof Error) return complete(delta);
2060 var where = this.$__where(delta[0]);
2070 this.$__reset();
2080 this.collection.update(where, delta[1], options, complete);
209 } else {
2100 this.$__reset();
2110 complete(null);
212 }
213
2140 this.emit('isNew', false);
215 }
216};
217
218/*!
219 * Apply the operation to the delta (update) clause as
220 * well as track versioning for our where clause.
221 *
222 * @param {Document} self
223 * @param {Object} where
224 * @param {Object} delta
225 * @param {Object} data
226 * @param {Mixed} val
227 * @param {String} [operation]
228 */
229
2301function operand (self, where, delta, data, val, op) {
231 // delta
2320 op || (op = '$set');
2330 if (!delta[op]) delta[op] = {};
2340 delta[op][data.path] = val;
235
236 // disabled versioning?
2370 if (false === self.schema.options.versionKey) return;
238
239 // already marked for versioning?
2400 if (VERSION_ALL === (VERSION_ALL & self.$__.version)) return;
241
2420 switch (op) {
243 case '$set':
244 case '$unset':
245 case '$pop':
246 case '$pull':
247 case '$pullAll':
248 case '$push':
249 case '$pushAll':
250 case '$addToSet':
2510 break;
252 default:
253 // nothing to do
2540 return;
255 }
256
257 // ensure updates sent with positional notation are
258 // editing the correct array element.
259 // only increment the version if an array position changes.
260 // modifying elements of an array is ok if position does not change.
261
2620 if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {
2630 self.$__.version = VERSION_INC;
264 }
2650 else if (/^\$p/.test(op)) {
266 // potentially changing array positions
2670 self.increment();
268 }
2690 else if (Array.isArray(val)) {
270 // $set an array
2710 self.increment();
272 }
273 // now handling $set, $unset
2740 else if (/\.\d+\.|\.\d+$/.test(data.path)) {
275 // subpath of array
2760 self.$__.version = VERSION_WHERE;
277 }
278}
279
280/*!
281 * Compiles an update and where clause for a `val` with _atomics.
282 *
283 * @param {Document} self
284 * @param {Object} where
285 * @param {Object} delta
286 * @param {Object} data
287 * @param {Array} value
288 */
289
2901function handleAtomics (self, where, delta, data, value) {
2910 if (delta.$set && delta.$set[data.path]) {
292 // $set has precedence over other atomics
2930 return;
294 }
295
2960 if ('function' == typeof value.$__getAtomics) {
2970 value.$__getAtomics().forEach(function (atomic) {
2980 var op = atomic[0];
2990 var val = atomic[1];
3000 operand(self, where, delta, data, val, op);
301 })
3020 return;
303 }
304
305 // legacy support for plugins
306
3070 var atomics = value._atomics
308 , ops = Object.keys(atomics)
309 , i = ops.length
310 , val
311 , op;
312
3130 if (0 === i) {
314 // $set
315
3160 if (isMongooseObject(value)) {
3170 value = value.toObject({ depopulate: 1 });
3180 } else if (value.valueOf) {
3190 value = value.valueOf();
320 }
321
3220 return operand(self, where, delta, data, value);
323 }
324
3250 while (i--) {
3260 op = ops[i];
3270 val = atomics[op];
328
3290 if (isMongooseObject(val)) {
3300 val = val.toObject({ depopulate: 1 })
3310 } else if (Array.isArray(val)) {
3320 val = val.map(function (mem) {
3330 return isMongooseObject(mem)
334 ? mem.toObject({ depopulate: 1 })
335 : mem;
336 })
3370 } else if (val.valueOf) {
3380 val = val.valueOf()
339 }
340
3410 if ('$addToSet' === op)
3420 val = { $each: val };
343
3440 operand(self, where, delta, data, val, op);
345 }
346}
347
348/**
349 * Produces a special query document of the modified properties used in updates.
350 *
351 * @api private
352 * @method $__delta
353 * @memberOf Model
354 */
355
3561Model.prototype.$__delta = function () {
3570 var dirty = this.$__dirty();
3580 if (!dirty.length && VERSION_ALL != this.$__.version) return;
359
3600 var where = {}
361 , delta = {}
362 , len = dirty.length
363 , divergent = []
364 , d = 0
365 , val
366 , obj
367
3680 for (; d < len; ++d) {
3690 var data = dirty[d]
3700 var value = data.value
3710 var schema = data.schema
372
3730 var match = checkDivergentArray(this, data.path, value);
3740 if (match) {
3750 divergent.push(match);
3760 continue;
377 }
378
3790 if (divergent.length) continue;
380
3810 if (undefined === value) {
3820 operand(this, where, delta, data, 1, '$unset');
383
3840 } else if (null === value) {
3850 operand(this, where, delta, data, null);
386
3870 } else if (value._path && value._atomics) {
388 // arrays and other custom types (support plugins etc)
3890 handleAtomics(this, where, delta, data, value);
390
3910 } else if (value._path && Buffer.isBuffer(value)) {
392 // MongooseBuffer
3930 value = value.toObject();
3940 operand(this, where, delta, data, value);
395
396 } else {
3970 value = utils.clone(value, { depopulate: 1 });
3980 operand(this, where, delta, data, value);
399 }
400 }
401
4020 if (divergent.length) {
4030 return new DivergentArrayError(divergent);
404 }
405
4060 if (this.$__.version) {
4070 this.$__version(where, delta);
408 }
409
4100 return [where, delta];
411}
412
413/*!
414 * Determine if array was populated with some form of filter and is now
415 * being updated in a manner which could overwrite data unintentionally.
416 *
417 * @see https://github.com/LearnBoost/mongoose/issues/1334
418 * @param {Document} doc
419 * @param {String} path
420 * @return {String|undefined}
421 */
422
4231function checkDivergentArray (doc, path, array) {
424 // see if we populated this path
4250 var pop = doc.populated(path, true);
426
4270 if (!pop && doc.$__.selected) {
428 // If any array was selected using an $elemMatch projection, we deny the update.
429 // NOTE: MongoDB only supports projected $elemMatch on top level array.
4300 var top = path.split('.')[0];
4310 if (doc.$__.selected[top] && doc.$__.selected[top].$elemMatch) {
4320 return top;
433 }
434 }
435
4360 if (!(pop && array instanceof MongooseArray)) return;
437
438 // If the array was populated using options that prevented all
439 // documents from being returned (match, skip, limit) or they
440 // deselected the _id field, $pop and $set of the array are
441 // not safe operations. If _id was deselected, we do not know
442 // how to remove elements. $pop will pop off the _id from the end
443 // of the array in the db which is not guaranteed to be the
444 // same as the last element we have here. $set of the entire array
445 // would be similarily destructive as we never received all
446 // elements of the array and potentially would overwrite data.
4470 var check = pop.options.match ||
448 pop.options.options && hasOwnProperty(pop.options.options, 'limit') || // 0 is not permitted
449 pop.options.options && pop.options.options.skip || // 0 is permitted
450 pop.options.select && // deselected _id?
451 (0 === pop.options.select._id ||
452 /\s?-_id\s?/.test(pop.options.select))
453
4540 if (check) {
4550 var atomics = array._atomics;
4560 if (0 === Object.keys(atomics).length || atomics.$set || atomics.$pop) {
4570 return path;
458 }
459 }
460}
461
462/**
463 * Appends versioning to the where and update clauses.
464 *
465 * @api private
466 * @method $__version
467 * @memberOf Model
468 */
469
4701Model.prototype.$__version = function (where, delta) {
4710 var key = this.schema.options.versionKey;
472
4730 if (true === where) {
474 // this is an insert
4750 if (key) this.setValue(key, delta[key] = 0);
4760 return;
477 }
478
479 // updates
480
481 // only apply versioning if our versionKey was selected. else
482 // there is no way to select the correct version. we could fail
483 // fast here and force them to include the versionKey but
484 // thats a bit intrusive. can we do this automatically?
4850 if (!this.isSelected(key)) {
4860 return;
487 }
488
489 // $push $addToSet don't need the where clause set
4900 if (VERSION_WHERE === (VERSION_WHERE & this.$__.version)) {
4910 where[key] = this.getValue(key);
492 }
493
4940 if (VERSION_INC === (VERSION_INC & this.$__.version)) {
4950 delta.$inc || (delta.$inc = {});
4960 delta.$inc[key] = 1;
497 }
498}
499
500/**
501 * Signal that we desire an increment of this documents version.
502 *
503 * ####Example:
504 *
505 * Model.findById(id, function (err, doc) {
506 * doc.increment();
507 * doc.save(function (err) { .. })
508 * })
509 *
510 * @see versionKeys http://mongoosejs.com/docs/guide.html#versionKey
511 * @api public
512 */
513
5141Model.prototype.increment = function increment () {
5150 this.$__.version = VERSION_ALL;
5160 return this;
517}
518
519/**
520 * Returns a query object which applies shardkeys if they exist.
521 *
522 * @api private
523 * @method $__where
524 * @memberOf Model
525 */
526
5271Model.prototype.$__where = function _where (where) {
5280 where || (where = {});
529
5300 var paths
531 , len
532
5330 if (this.$__.shardval) {
5340 paths = Object.keys(this.$__.shardval)
5350 len = paths.length
536
5370 for (var i = 0; i < len; ++i) {
5380 where[paths[i]] = this.$__.shardval[paths[i]];
539 }
540 }
541
5420 where._id = this._doc._id;
5430 return where;
544}
545
546/**
547 * Removes this document from the db.
548 *
549 * ####Example:
550 *
551 * product.remove(function (err, product) {
552 * if (err) return handleError(err);
553 * Product.findById(product._id, function (err, product) {
554 * console.log(product) // null
555 * })
556 * })
557 *
558 * @param {Function} [fn] optional callback
559 * @api public
560 */
561
5621Model.prototype.remove = function remove (fn) {
5630 if (this.$__.removing) {
5640 this.$__.removing.addBack(fn);
5650 return this;
566 }
567
5680 var promise = this.$__.removing = new Promise(fn)
569 , where = this.$__where()
570 , self = this
571 , options = {}
572
5730 if (this.schema.options.safe) {
5740 options.safe = this.schema.options.safe;
575 }
576
5770 this.collection.remove(where, options, tick(function (err) {
5780 if (err) {
5790 promise.error(err);
5800 promise = self = self.$__.removing = where = options = null;
5810 return;
582 }
5830 self.emit('remove', self);
5840 promise.complete(self);
5850 promise = self = where = options = null;
586 }));
587
5880 return this;
589};
590
591/**
592 * Returns another Model instance.
593 *
594 * ####Example:
595 *
596 * var doc = new Tank;
597 * doc.model('User').findById(id, callback);
598 *
599 * @param {String} name model name
600 * @api public
601 */
602
6031Model.prototype.model = function model (name) {
6040 return this.db.model(name);
605};
606
607/**
608 * Adds a discriminator type.
609 *
610 * ####Example:
611 *
612 * function BaseSchema() {
613 * Schema.apply(this, arguments);
614 *
615 * this.add({
616 * name: String,
617 * createdAt: Date
618 * });
619 * }
620 * util.inherits(BaseSchema, Schema);
621 *
622 * var PersonSchema = new BaseSchema();
623 * var BossSchema = new BaseSchema({ department: String });
624 *
625 * var Person = mongoose.model('Person', PersonSchema);
626 * var Boss = Person.discriminator('Boss', BossSchema);
627 *
628 * @param {String} name discriminator model name
629 * @param {Schema} schema discriminator model schema
630 * @api public
631 */
632
6331Model.discriminator = function discriminator (name, schema) {
6340 if (!(schema instanceof Schema)) {
6350 throw new Error("You must pass a valid discriminator Schema");
636 }
637
6380 if (this.schema.discriminatorMapping && !this.schema.discriminatorMapping.isRoot) {
6390 throw new Error("Discriminator \"" + name + "\" can only be a discriminator of the root model");
640 }
641
6420 var key = this.schema.options.discriminatorKey;
6430 if (schema.path(key)) {
6440 throw new Error("Discriminator \"" + name + "\" cannot have field with name \"" + key + "\"");
645 }
646
647 // merges base schema into new discriminator schema and sets new type field.
6480 (function mergeSchemas(schema, baseSchema) {
6490 utils.merge(schema, baseSchema);
650
6510 var obj = {};
6520 obj[key] = { type: String, default: name };
6530 schema.add(obj);
6540 schema.discriminatorMapping = { key: key, value: name, isRoot: false };
655
6560 if (baseSchema.options.collection) {
6570 schema.options.collection = baseSchema.options.collection;
658 }
659
660 // throws error if options are invalid
6610 (function validateOptions(a, b) {
6620 a = utils.clone(a);
6630 b = utils.clone(b);
6640 delete a.toJSON;
6650 delete a.toObject;
6660 delete b.toJSON;
6670 delete b.toObject;
668
6690 if (!utils.deepEqual(a, b)) {
6700 throw new Error("Discriminator options are not customizable (except toJSON & toObject)");
671 }
672 })(schema.options, baseSchema.options);
673
6740 var toJSON = schema.options.toJSON
675 , toObject = schema.options.toObject;
676
6770 schema.options = utils.clone(baseSchema.options);
6780 if (toJSON) schema.options.toJSON = toJSON;
6790 if (toObject) schema.options.toObject = toObject;
680
6810 schema.callQueue = baseSchema.callQueue.concat(schema.callQueue);
6820 schema._requiredpaths = undefined; // reset just in case Schema#requiredPaths() was called on either schema
683 })(schema, this.schema);
684
6850 if (!this.discriminators) {
6860 this.discriminators = {};
687 }
688
6890 if (!this.schema.discriminatorMapping) {
6900 this.schema.discriminatorMapping = { key: key, value: null, isRoot: true };
691 }
692
6930 if (this.discriminators[name]) {
6940 throw new Error("Discriminator with name \"" + name + "\" already exists");
695 }
696
6970 this.discriminators[name] = this.db.model(name, schema, this.collection.name);
6980 this.discriminators[name].prototype.__proto__ = this.prototype;
699
7000 return this.discriminators[name];
701};
702
703// Model (class) features
704
705/*!
706 * Give the constructor the ability to emit events.
707 */
708
7091for (var i in EventEmitter.prototype)
7108 Model[i] = EventEmitter.prototype[i];
711
712/**
713 * Called when the model compiles.
714 *
715 * @api private
716 */
717
7181Model.init = function init () {
7190 if (this.schema.options.autoIndex) {
7200 this.ensureIndexes();
721 }
722
7230 this.schema.emit('init', this);
724};
725
726/**
727 * Sends `ensureIndex` commands to mongo for each index declared in the schema.
728 *
729 * ####Example:
730 *
731 * Event.ensureIndexes(function (err) {
732 * if (err) return handleError(err);
733 * });
734 *
735 * After completion, an `index` event is emitted on this `Model` passing an error if one occurred.
736 *
737 * ####Example:
738 *
739 * var eventSchema = new Schema({ thing: { type: 'string', unique: true }})
740 * var Event = mongoose.model('Event', eventSchema);
741 *
742 * Event.on('index', function (err) {
743 * if (err) console.error(err); // error occurred during index creation
744 * })
745 *
746 * _NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution._
747 *
748 * The `ensureIndex` commands are not sent in parallel. This is to avoid the `MongoError: cannot add index with a background operation in progress` error. See [this ticket](https://github.com/LearnBoost/mongoose/issues/1365) for more information.
749 *
750 * @param {Function} [cb] optional callback
751 * @return {Promise}
752 * @api public
753 */
754
7551Model.ensureIndexes = function ensureIndexes (cb) {
7560 var promise = new Promise(cb);
757
7580 var indexes = this.schema.indexes();
7590 if (!indexes.length) {
7600 process.nextTick(promise.fulfill.bind(promise));
7610 return promise;
762 }
763
764 // Indexes are created one-by-one to support how MongoDB < 2.4 deals
765 // with background indexes.
766
7670 var self = this
768 , safe = self.schema.options.safe
769
7700 function done (err) {
7710 self.emit('index', err);
7720 promise.resolve(err);
773 }
774
7750 function create () {
7760 var index = indexes.shift();
7770 if (!index) return done();
778
7790 var options = index[1];
7800 options.safe = safe;
7810 self.collection.ensureIndex(index[0], options, tick(function (err) {
7820 if (err) return done(err);
7830 create();
784 }));
785 }
786
7870 create();
7880 return promise;
789}
790
791/**
792 * Schema the model uses.
793 *
794 * @property schema
795 * @receiver Model
796 * @api public
797 */
798
7991Model.schema;
800
801/*!
802 * Connection instance the model uses.
803 *
804 * @property db
805 * @receiver Model
806 * @api public
807 */
808
8091Model.db;
810
811/*!
812 * Collection the model uses.
813 *
814 * @property collection
815 * @receiver Model
816 * @api public
817 */
818
8191Model.collection;
820
821/**
822 * Base Mongoose instance the model uses.
823 *
824 * @property base
825 * @receiver Model
826 * @api public
827 */
828
8291Model.base;
830
831/**
832 * Registered discriminators for this model.
833 *
834 * @property discriminators
835 * @receiver Model
836 * @api public
837 */
838
8391Model.discriminators;
840
841/**
842 * Removes documents from the collection.
843 *
844 * ####Example:
845 *
846 * Comment.remove({ title: 'baby born from alien father' }, function (err) {
847 *
848 * });
849 *
850 * ####Note:
851 *
852 * To remove documents without waiting for a response from MongoDB, do not pass a `callback`, then call `exec` on the returned [Query](#query-js):
853 *
854 * var query = Comment.remove({ _id: id });
855 * query.exec();
856 *
857 * ####Note:
858 *
859 * This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, _no middleware (hooks) are executed_.
860 *
861 * @param {Object} conditions
862 * @param {Function} [callback]
863 * @return {Query}
864 * @api public
865 */
866
8671Model.remove = function remove (conditions, callback) {
8680 if ('function' === typeof conditions) {
8690 callback = conditions;
8700 conditions = {};
871 }
872
873 // get the mongodb collection object
8740 var mq = new Query(conditions, {}, this, this.collection);
875
8760 return mq.remove(callback);
877};
878
879/**
880 * Finds documents
881 *
882 * The `conditions` are cast to their respective SchemaTypes before the command is sent.
883 *
884 * ####Examples:
885 *
886 * // named john and at least 18
887 * MyModel.find({ name: 'john', age: { $gte: 18 }});
888 *
889 * // executes immediately, passing results to callback
890 * MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});
891 *
892 * // name LIKE john and only selecting the "name" and "friends" fields, executing immediately
893 * MyModel.find({ name: /john/i }, 'name friends', function (err, docs) { })
894 *
895 * // passing options
896 * MyModel.find({ name: /john/i }, null, { skip: 10 })
897 *
898 * // passing options and executing immediately
899 * MyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {});
900 *
901 * // executing a query explicitly
902 * var query = MyModel.find({ name: /john/i }, null, { skip: 10 })
903 * query.exec(function (err, docs) {});
904 *
905 * // using the promise returned from executing a query
906 * var query = MyModel.find({ name: /john/i }, null, { skip: 10 });
907 * var promise = query.exec();
908 * promise.addBack(function (err, docs) {});
909 *
910 * @param {Object} conditions
911 * @param {Object} [fields] optional fields to select
912 * @param {Object} [options] optional
913 * @param {Function} [callback]
914 * @return {Query}
915 * @see field selection #query_Query-select
916 * @see promise #promise-js
917 * @api public
918 */
919
9201Model.find = function find (conditions, fields, options, callback) {
9210 if ('function' == typeof conditions) {
9220 callback = conditions;
9230 conditions = {};
9240 fields = null;
9250 options = null;
9260 } else if ('function' == typeof fields) {
9270 callback = fields;
9280 fields = null;
9290 options = null;
9300 } else if ('function' == typeof options) {
9310 callback = options;
9320 options = null;
933 }
934
935 // get the raw mongodb collection object
9360 var mq = new Query({}, options, this, this.collection);
9370 mq.select(fields);
9380 if (this.schema.discriminatorMapping && mq._selectedInclusively()) {
9390 mq.select(this.schema.options.discriminatorKey);
940 }
941
9420 return mq.find(conditions, callback);
943};
944
945/**
946 * Finds a single document by id.
947 *
948 * The `id` is cast based on the Schema before sending the command.
949 *
950 * ####Example:
951 *
952 * // find adventure by id and execute immediately
953 * Adventure.findById(id, function (err, adventure) {});
954 *
955 * // same as above
956 * Adventure.findById(id).exec(callback);
957 *
958 * // select only the adventures name and length
959 * Adventure.findById(id, 'name length', function (err, adventure) {});
960 *
961 * // same as above
962 * Adventure.findById(id, 'name length').exec(callback);
963 *
964 * // include all properties except for `length`
965 * Adventure.findById(id, '-length').exec(function (err, adventure) {});
966 *
967 * // passing options (in this case return the raw js objects, not mongoose documents by passing `lean`
968 * Adventure.findById(id, 'name', { lean: true }, function (err, doc) {});
969 *
970 * // same as above
971 * Adventure.findById(id, 'name').lean().exec(function (err, doc) {});
972 *
973 * @param {ObjectId|HexId} id objectid, or a value that can be casted to one
974 * @param {Object} [fields] optional fields to select
975 * @param {Object} [options] optional
976 * @param {Function} [callback]
977 * @return {Query}
978 * @see field selection #query_Query-select
979 * @see lean queries #query_Query-lean
980 * @api public
981 */
982
9831Model.findById = function findById (id, fields, options, callback) {
9840 return this.findOne({ _id: id }, fields, options, callback);
985};
986
987/**
988 * Finds one document.
989 *
990 * The `conditions` are cast to their respective SchemaTypes before the command is sent.
991 *
992 * ####Example:
993 *
994 * // find one iphone adventures - iphone adventures??
995 * Adventure.findOne({ type: 'iphone' }, function (err, adventure) {});
996 *
997 * // same as above
998 * Adventure.findOne({ type: 'iphone' }).exec(function (err, adventure) {});
999 *
1000 * // select only the adventures name
1001 * Adventure.findOne({ type: 'iphone' }, 'name', function (err, adventure) {});
1002 *
1003 * // same as above
1004 * Adventure.findOne({ type: 'iphone' }, 'name').exec(function (err, adventure) {});
1005 *
1006 * // specify options, in this case lean
1007 * Adventure.findOne({ type: 'iphone' }, 'name', { lean: true }, callback);
1008 *
1009 * // same as above
1010 * Adventure.findOne({ type: 'iphone' }, 'name', { lean: true }).exec(callback);
1011 *
1012 * // chaining findOne queries (same as above)
1013 * Adventure.findOne({ type: 'iphone' }).select('name').lean().exec(callback);
1014 *
1015 * @param {Object} conditions
1016 * @param {Object} [fields] optional fields to select
1017 * @param {Object} [options] optional
1018 * @param {Function} [callback]
1019 * @return {Query}
1020 * @see field selection #query_Query-select
1021 * @see lean queries #query_Query-lean
1022 * @api public
1023 */
1024
10251Model.findOne = function findOne (conditions, fields, options, callback) {
10260 if ('function' == typeof options) {
10270 callback = options;
10280 options = null;
10290 } else if ('function' == typeof fields) {
10300 callback = fields;
10310 fields = null;
10320 options = null;
10330 } else if ('function' == typeof conditions) {
10340 callback = conditions;
10350 conditions = {};
10360 fields = null;
10370 options = null;
1038 }
1039
1040 // get the mongodb collection object
10410 var mq = new Query({}, options, this, this.collection);
10420 mq.select(fields);
10430 if (this.schema.discriminatorMapping && mq._selectedInclusively()) {
10440 mq.select(this.schema.options.discriminatorKey);
1045 }
1046
10470 return mq.findOne(conditions, callback);
1048};
1049
1050/**
1051 * Counts number of matching documents in a database collection.
1052 *
1053 * ####Example:
1054 *
1055 * Adventure.count({ type: 'jungle' }, function (err, count) {
1056 * if (err) ..
1057 * console.log('there are %d jungle adventures', count);
1058 * });
1059 *
1060 * @param {Object} conditions
1061 * @param {Function} [callback]
1062 * @return {Query}
1063 * @api public
1064 */
1065
10661Model.count = function count (conditions, callback) {
10670 if ('function' === typeof conditions)
10680 callback = conditions, conditions = {};
1069
1070 // get the mongodb collection object
10710 var mq = new Query({}, {}, this, this.collection);
1072
10730 return mq.count(conditions, callback);
1074};
1075
1076/**
1077 * Creates a Query for a `distinct` operation.
1078 *
1079 * Passing a `callback` immediately executes the query.
1080 *
1081 * ####Example
1082 *
1083 * Link.distinct('url', { clicks: {$gt: 100}}, function (err, result) {
1084 * if (err) return handleError(err);
1085 *
1086 * assert(Array.isArray(result));
1087 * console.log('unique urls with more than 100 clicks', result);
1088 * })
1089 *
1090 * var query = Link.distinct('url');
1091 * query.exec(callback);
1092 *
1093 * @param {String} field
1094 * @param {Object} [conditions] optional
1095 * @param {Function} [callback]
1096 * @return {Query}
1097 * @api public
1098 */
1099
11001Model.distinct = function distinct (field, conditions, callback) {
1101 // get the mongodb collection object
11020 var mq = new Query({}, {}, this, this.collection);
1103
11040 if ('function' == typeof conditions) {
11050 callback = conditions;
11060 conditions = {};
1107 }
1108
11090 return mq.distinct(conditions, field, callback);
1110};
1111
1112/**
1113 * Creates a Query, applies the passed conditions, and returns the Query.
1114 *
1115 * For example, instead of writing:
1116 *
1117 * User.find({age: {$gte: 21, $lte: 65}}, callback);
1118 *
1119 * we can instead write:
1120 *
1121 * User.where('age').gte(21).lte(65).exec(callback);
1122 *
1123 * Since the Query class also supports `where` you can continue chaining
1124 *
1125 * User
1126 * .where('age').gte(21).lte(65)
1127 * .where('name', /^b/i)
1128 * ... etc
1129 *
1130 * @param {String} path
1131 * @param {Object} [val] optional value
1132 * @return {Query}
1133 * @api public
1134 */
1135
11361Model.where = function where (path, val) {
1137 // get the mongodb collection object
11380 var mq = new Query({}, {}, this, this.collection).find({});
11390 return mq.where.apply(mq, arguments);
1140};
1141
1142/**
1143 * Creates a `Query` and specifies a `$where` condition.
1144 *
1145 * Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via `find({ $where: javascript })`, or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.
1146 *
1147 * Blog.$where('this.comments.length > 5').exec(function (err, docs) {});
1148 *
1149 * @param {String|Function} argument is a javascript string or anonymous function
1150 * @method $where
1151 * @memberOf Model
1152 * @return {Query}
1153 * @see Query.$where #query_Query-%24where
1154 * @api public
1155 */
1156
11571Model.$where = function $where () {
11580 var mq = new Query({}, {}, this, this.collection).find({});
11590 return mq.$where.apply(mq, arguments);
1160};
1161
1162/**
1163 * Issues a mongodb findAndModify update command.
1164 *
1165 * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned.
1166 *
1167 * ####Options:
1168 *
1169 * - `new`: bool - true to return the modified document rather than the original. defaults to true
1170 * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
1171 * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
1172 * - `select`: sets the document fields to return
1173 *
1174 * ####Examples:
1175 *
1176 * A.findOneAndUpdate(conditions, update, options, callback) // executes
1177 * A.findOneAndUpdate(conditions, update, options) // returns Query
1178 * A.findOneAndUpdate(conditions, update, callback) // executes
1179 * A.findOneAndUpdate(conditions, update) // returns Query
1180 * A.findOneAndUpdate() // returns Query
1181 *
1182 * ####Note:
1183 *
1184 * All top level update keys which are not `atomic` operation names are treated as set operations:
1185 *
1186 * ####Example:
1187 *
1188 * var query = { name: 'borne' };
1189 * Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
1190 *
1191 * // is sent as
1192 * Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
1193 *
1194 * This helps prevent accidentally overwriting your document with `{ name: 'jason borne' }`.
1195 *
1196 * ####Note:
1197 *
1198 * Although values are cast to their appropriate types when using the findAndModify helpers, the following are *not* applied:
1199 *
1200 * - defaults
1201 * - setters
1202 * - validators
1203 * - middleware
1204 *
1205 * If you need those features, use the traditional approach of first retrieving the document.
1206 *
1207 * Model.findOne({ name: 'borne' }, function (err, doc) {
1208 * if (err) ..
1209 * doc.name = 'jason borne';
1210 * doc.save(callback);
1211 * })
1212 *
1213 * @param {Object} [conditions]
1214 * @param {Object} [update]
1215 * @param {Object} [options]
1216 * @param {Function} [callback]
1217 * @return {Query}
1218 * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
1219 * @api public
1220 */
1221
12221Model.findOneAndUpdate = function (conditions, update, options, callback) {
12230 if ('function' == typeof options) {
12240 callback = options;
12250 options = null;
1226 }
12270 else if (1 === arguments.length) {
12280 if ('function' == typeof conditions) {
12290 var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\n\n'
1230 + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\n'
1231 + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\n'
1232 + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\n'
1233 + ' ' + this.modelName + '.findOneAndUpdate(update)\n'
1234 + ' ' + this.modelName + '.findOneAndUpdate()\n';
12350 throw new TypeError(msg)
1236 }
12370 update = conditions;
12380 conditions = undefined;
1239 }
1240
12410 var fields;
12420 if (options && options.fields) {
12430 fields = options.fields;
12440 options.fields = undefined;
1245 }
1246
12470 var mq = new Query({}, {}, this, this.collection);
12480 mq.select(fields);
1249
12500 return mq.findOneAndUpdate(conditions, update, options, callback);
1251}
1252
1253/**
1254 * Issues a mongodb findAndModify update command by a documents id.
1255 *
1256 * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned.
1257 *
1258 * ####Options:
1259 *
1260 * - `new`: bool - true to return the modified document rather than the original. defaults to true
1261 * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
1262 * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
1263 * - `select`: sets the document fields to return
1264 *
1265 * ####Examples:
1266 *
1267 * A.findByIdAndUpdate(id, update, options, callback) // executes
1268 * A.findByIdAndUpdate(id, update, options) // returns Query
1269 * A.findByIdAndUpdate(id, update, callback) // executes
1270 * A.findByIdAndUpdate(id, update) // returns Query
1271 * A.findByIdAndUpdate() // returns Query
1272 *
1273 * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned.
1274 *
1275 * ####Options:
1276 *
1277 * - `new`: bool - true to return the modified document rather than the original. defaults to true
1278 * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
1279 * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
1280 *
1281 * ####Note:
1282 *
1283 * All top level update keys which are not `atomic` operation names are treated as set operations:
1284 *
1285 * ####Example:
1286 *
1287 * Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
1288 *
1289 * // is sent as
1290 * Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
1291 *
1292 * This helps prevent accidentally overwriting your document with `{ name: 'jason borne' }`.
1293 *
1294 * ####Note:
1295 *
1296 * Although values are cast to their appropriate types when using the findAndModify helpers, the following are *not* applied:
1297 *
1298 * - defaults
1299 * - setters
1300 * - validators
1301 * - middleware
1302 *
1303 * If you need those features, use the traditional approach of first retrieving the document.
1304 *
1305 * Model.findById(id, function (err, doc) {
1306 * if (err) ..
1307 * doc.name = 'jason borne';
1308 * doc.save(callback);
1309 * })
1310 *
1311 * @param {ObjectId|HexId} id an ObjectId or string that can be cast to one.
1312 * @param {Object} [update]
1313 * @param {Object} [options]
1314 * @param {Function} [callback]
1315 * @return {Query}
1316 * @see Model.findOneAndUpdate #model_Model.findOneAndUpdate
1317 * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
1318 * @api public
1319 */
1320
13211Model.findByIdAndUpdate = function (id, update, options, callback) {
13220 var args;
1323
13240 if (1 === arguments.length) {
13250 if ('function' == typeof id) {
13260 var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
1327 + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
1328 + ' ' + this.modelName + '.findByIdAndUpdate(id)\n'
1329 + ' ' + this.modelName + '.findByIdAndUpdate()\n';
13300 throw new TypeError(msg)
1331 }
13320 return this.findOneAndUpdate({_id: id }, undefined);
1333 }
1334
13350 args = utils.args(arguments, 1);
1336
1337 // if a model is passed in instead of an id
13380 if (id && id._id) {
13390 id = id._id;
1340 }
13410 if (id) {
13420 args.unshift({ _id: id });
1343 }
13440 return this.findOneAndUpdate.apply(this, args);
1345}
1346
1347/**
1348 * Issue a mongodb findAndModify remove command.
1349 *
1350 * Finds a matching document, removes it, passing the found document (if any) to the callback.
1351 *
1352 * Executes immediately if `callback` is passed else a Query object is returned.
1353 *
1354 * ####Options:
1355 *
1356 * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
1357 * - `select`: sets the document fields to return
1358 *
1359 * ####Examples:
1360 *
1361 * A.findOneAndRemove(conditions, options, callback) // executes
1362 * A.findOneAndRemove(conditions, options) // return Query
1363 * A.findOneAndRemove(conditions, callback) // executes
1364 * A.findOneAndRemove(conditions) // returns Query
1365 * A.findOneAndRemove() // returns Query
1366 *
1367 * Although values are cast to their appropriate types when using the findAndModify helpers, the following are *not* applied:
1368 *
1369 * - defaults
1370 * - setters
1371 * - validators
1372 * - middleware
1373 *
1374 * If you need those features, use the traditional approach of first retrieving the document.
1375 *
1376 * Model.findById(id, function (err, doc) {
1377 * if (err) ..
1378 * doc.remove(callback);
1379 * })
1380 *
1381 * @param {Object} conditions
1382 * @param {Object} [options]
1383 * @param {Function} [callback]
1384 * @return {Query}
1385 * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
1386 * @api public
1387 */
1388
13891Model.findOneAndRemove = function (conditions, options, callback) {
13900 if (1 === arguments.length && 'function' == typeof conditions) {
13910 var msg = 'Model.findOneAndRemove(): First argument must not be a function.\n\n'
1392 + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\n'
1393 + ' ' + this.modelName + '.findOneAndRemove(conditions)\n'
1394 + ' ' + this.modelName + '.findOneAndRemove()\n';
13950 throw new TypeError(msg)
1396 }
1397
13980 if ('function' == typeof options) {
13990 callback = options;
14000 options = undefined;
1401 }
1402
14030 var fields;
14040 if (options) {
14050 fields = options.select;
14060 options.select = undefined;
1407 }
1408
14090 var mq = new Query({}, {}, this, this.collection);
14100 mq.select(fields);
1411
14120 return mq.findOneAndRemove(conditions, options, callback);
1413}
1414
1415/**
1416 * Issue a mongodb findAndModify remove command by a documents id.
1417 *
1418 * Finds a matching document, removes it, passing the found document (if any) to the callback.
1419 *
1420 * Executes immediately if `callback` is passed, else a `Query` object is returned.
1421 *
1422 * ####Options:
1423 *
1424 * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
1425 * - `select`: sets the document fields to return
1426 *
1427 * ####Examples:
1428 *
1429 * A.findByIdAndRemove(id, options, callback) // executes
1430 * A.findByIdAndRemove(id, options) // return Query
1431 * A.findByIdAndRemove(id, callback) // executes
1432 * A.findByIdAndRemove(id) // returns Query
1433 * A.findByIdAndRemove() // returns Query
1434 *
1435 * @param {ObjectId|HexString} id ObjectId or string that can be cast to one
1436 * @param {Object} [options]
1437 * @param {Function} [callback]
1438 * @return {Query}
1439 * @see Model.findOneAndRemove #model_Model.findOneAndRemove
1440 * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
1441 */
1442
14431Model.findByIdAndRemove = function (id, options, callback) {
14440 if (1 === arguments.length && 'function' == typeof id) {
14450 var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\n\n'
1446 + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\n'
1447 + ' ' + this.modelName + '.findByIdAndRemove(id)\n'
1448 + ' ' + this.modelName + '.findByIdAndRemove()\n';
14490 throw new TypeError(msg)
1450 }
1451
14520 return this.findOneAndRemove({ _id: id }, options, callback);
1453}
1454
1455/**
1456 * Shortcut for creating a new Document that is automatically saved to the db if valid.
1457 *
1458 * ####Example:
1459 *
1460 * // pass individual docs
1461 * Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
1462 * if (err) // ...
1463 * });
1464 *
1465 * // pass an array
1466 * var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
1467 * Candy.create(array, function (err, jellybean, snickers) {
1468 * if (err) // ...
1469 * });
1470 *
1471 * // callback is optional; use the returned promise if you like:
1472 * var promise = Candy.create({ type: 'jawbreaker' });
1473 * promise.then(function (jawbreaker) {
1474 * // ...
1475 * })
1476 *
1477 * @param {Array|Object...} doc(s)
1478 * @param {Function} [fn] callback
1479 * @return {Promise}
1480 * @api public
1481 */
1482
14831Model.create = function create (doc, fn) {
14840 var promise = new Promise
1485 , args
1486
14870 if (Array.isArray(doc)) {
14880 args = doc;
1489
14900 if ('function' == typeof fn) {
14910 promise.onResolve(fn);
1492 }
1493
1494 } else {
14950 var last = arguments[arguments.length - 1];
1496
14970 if ('function' == typeof last) {
14980 promise.onResolve(last);
14990 args = utils.args(arguments, 0, arguments.length - 1);
1500 } else {
15010 args = utils.args(arguments);
1502 }
1503 }
1504
15050 var count = args.length;
1506
15070 if (0 === count) {
15080 promise.complete();
15090 return promise;
1510 }
1511
15120 var self = this;
15130 var docs = [];
1514
15150 args.forEach(function (arg, i) {
15160 var doc = new self(arg);
15170 docs[i] = doc;
15180 doc.save(function (err) {
15190 if (err) return promise.error(err);
15200 --count || promise.complete.apply(promise, docs);
1521 });
1522 });
1523
15240 return promise;
1525};
1526
1527/**
1528 * Updates documents in the database without returning them.
1529 *
1530 * ####Examples:
1531 *
1532 * MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
1533 * MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
1534 * if (err) return handleError(err);
1535 * console.log('The number of updated documents was %d', numberAffected);
1536 * console.log('The raw response from Mongo was ', raw);
1537 * });
1538 *
1539 * ####Valid options:
1540 *
1541 * - `safe` (boolean) safe mode (defaults to value set in schema (true))
1542 * - `upsert` (boolean) whether to create the doc if it doesn't match (false)
1543 * - `multi` (boolean) whether multiple documents should be updated (false)
1544 * - `strict` (boolean) overrides the `strict` option for this update
1545 *
1546 * All `update` values are cast to their appropriate SchemaTypes before being sent.
1547 *
1548 * The `callback` function receives `(err, numberAffected, rawResponse)`.
1549 *
1550 * - `err` is the error if any occurred
1551 * - `numberAffected` is the count of updated documents Mongo reported
1552 * - `rawResponse` is the full response from Mongo
1553 *
1554 * ####Note:
1555 *
1556 * All top level keys which are not `atomic` operation names are treated as set operations:
1557 *
1558 * ####Example:
1559 *
1560 * var query = { name: 'borne' };
1561 * Model.update(query, { name: 'jason borne' }, options, callback)
1562 *
1563 * // is sent as
1564 * Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
1565 *
1566 * This helps prevent accidentally overwriting all documents in your collection with `{ name: 'jason borne' }`.
1567 *
1568 * ####Note:
1569 *
1570 * Be careful to not use an existing model instance for the update clause (this won't work and can cause weird behavior like infinite loops). Also, ensure that the update clause does not have an _id property, which causes Mongo to return a "Mod on _id not allowed" error.
1571 *
1572 * ####Note:
1573 *
1574 * To update documents without waiting for a response from MongoDB, do not pass a `callback`, then call `exec` on the returned [Query](#query-js):
1575 *
1576 * Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
1577 *
1578 * ####Note:
1579 *
1580 * Although values are casted to their appropriate types when using update, the following are *not* applied:
1581 *
1582 * - defaults
1583 * - setters
1584 * - validators
1585 * - middleware
1586 *
1587 * If you need those features, use the traditional approach of first retrieving the document.
1588 *
1589 * Model.findOne({ name: 'borne' }, function (err, doc) {
1590 * if (err) ..
1591 * doc.name = 'jason borne';
1592 * doc.save(callback);
1593 * })
1594 *
1595 * @see strict http://mongoosejs.com/docs/guide.html#strict
1596 * @param {Object} conditions
1597 * @param {Object} update
1598 * @param {Object} [options]
1599 * @param {Function} [callback]
1600 * @return {Query}
1601 * @api public
1602 */
1603
16041Model.update = function update (conditions, doc, options, callback) {
16050 var mq = new Query({}, {}, this, this.collection);
16060 return mq.update(conditions, doc, options, callback);
1607};
1608
1609/**
1610 * Executes a mapReduce command.
1611 *
1612 * `o` is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.
1613 *
1614 * ####Example:
1615 *
1616 * var o = {};
1617 * o.map = function () { emit(this.name, 1) }
1618 * o.reduce = function (k, vals) { return vals.length }
1619 * User.mapReduce(o, function (err, results) {
1620 * console.log(results)
1621 * })
1622 *
1623 * ####Other options:
1624 *
1625 * - `query` {Object} query filter object.
1626 * - `limit` {Number} max number of documents
1627 * - `keeptemp` {Boolean, default:false} keep temporary data
1628 * - `finalize` {Function} finalize function
1629 * - `scope` {Object} scope variables exposed to map/reduce/finalize during execution
1630 * - `jsMode` {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
1631 * - `verbose` {Boolean, default:false} provide statistics on job execution time.
1632 * - `out*` {Object, default: {inline:1}} sets the output target for the map reduce job.
1633 *
1634 * ####* out options:
1635 *
1636 * - `{inline:1}` the results are returned in an array
1637 * - `{replace: 'collectionName'}` add the results to collectionName: the results replace the collection
1638 * - `{reduce: 'collectionName'}` add the results to collectionName: if dups are detected, uses the reducer / finalize functions
1639 * - `{merge: 'collectionName'}` add the results to collectionName: if dups exist the new docs overwrite the old
1640 *
1641 * If `options.out` is set to `replace`, `merge`, or `reduce`, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the `lean` option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).
1642 *
1643 * ####Example:
1644 *
1645 * var o = {};
1646 * o.map = function () { emit(this.name, 1) }
1647 * o.reduce = function (k, vals) { return vals.length }
1648 * o.out = { replace: 'createdCollectionNameForResults' }
1649 * o.verbose = true;
1650 *
1651 * User.mapReduce(o, function (err, model, stats) {
1652 * console.log('map reduce took %d ms', stats.processtime)
1653 * model.find().where('value').gt(10).exec(function (err, docs) {
1654 * console.log(docs);
1655 * });
1656 * })
1657 *
1658 * // a promise is returned so you may instead write
1659 * var promise = User.mapReduce(o);
1660 * promise.then(function (model, stats) {
1661 * console.log('map reduce took %d ms', stats.processtime)
1662 * return model.find().where('value').gt(10).exec();
1663 * }).then(function (docs) {
1664 * console.log(docs);
1665 * }).then(null, handleError).end()
1666 *
1667 * @param {Object} o an object specifying map-reduce options
1668 * @param {Function} [callback] optional callback
1669 * @see http://www.mongodb.org/display/DOCS/MapReduce
1670 * @return {Promise}
1671 * @api public
1672 */
1673
16741Model.mapReduce = function mapReduce (o, callback) {
16750 var promise = new Promise(callback);
16760 var self = this;
1677
16780 if (!Model.mapReduce.schema) {
16790 var opts = { noId: true, noVirtualId: true, strict: false }
16800 Model.mapReduce.schema = new Schema({}, opts);
1681 }
1682
16830 if (!o.out) o.out = { inline: 1 };
16840 if (false !== o.verbose) o.verbose = true;
1685
16860 o.map = String(o.map);
16870 o.reduce = String(o.reduce);
1688
16890 if (o.query) {
16900 var q = new Query(o.query);
16910 q.cast(this);
16920 o.query = q._conditions;
16930 q = undefined;
1694 }
1695
16960 this.collection.mapReduce(null, null, o, function (err, ret, stats) {
16970 if (err) return promise.error(err);
1698
16990 if (ret.findOne && ret.mapReduce) {
1700 // returned a collection, convert to Model
17010 var model = Model.compile(
1702 '_mapreduce_' + ret.collectionName
1703 , Model.mapReduce.schema
1704 , ret.collectionName
1705 , self.db
1706 , self.base);
1707
17080 model._mapreduce = true;
1709
17100 return promise.fulfill(model, stats);
1711 }
1712
17130 promise.fulfill(ret, stats);
1714 });
1715
17160 return promise;
1717}
1718
1719/**
1720 * geoNear support for Mongoose
1721 *
1722 * ####Options:
1723 * - `lean` {Boolean} return the raw object
1724 * - All options supported by the driver are also supported
1725 *
1726 * ####Example:
1727 *
1728 * // Legacy point
1729 * Model.geoNear([1,3], { maxDistance : 5, spherical : true }, function(err, results, stats) {
1730 * console.log(results);
1731 * });
1732 *
1733 * // geoJson
1734 * var point = { type : "Point", coordinates : [9,9] };
1735 * Model.geoNear(point, { maxDistance : 5, spherical : true }, function(err, results, stats) {
1736 * console.log(results);
1737 * });
1738 *
1739 * @param {Object/Array} GeoJSON point or legacy coordinate pair [x,y] to search near
1740 * @param {Object} options for the qurery
1741 * @param {Function} [callback] optional callback for the query
1742 * @return {Promise}
1743 * @see http://docs.mongodb.org/manual/core/2dsphere/
1744 * @see http://mongodb.github.io/node-mongodb-native/api-generated/collection.html?highlight=geonear#geoNear
1745 * @api public
1746 */
1747
17481Model.geoNear = function (near, options, callback) {
17490 if ('function' == typeof options) {
17500 callback = options;
17510 options = {};
1752 }
1753
17540 var promise = new Promise(callback);
17550 if (!near) {
17560 promise.error(new Error("Must pass a near option to geoNear"));
17570 return promise;
1758 }
1759
17600 var x,y;
1761
17620 if (Array.isArray(near)) {
17630 if (near.length != 2) {
17640 promise.error(new Error("If using legacy coordinates, must be an array of size 2 for geoNear"));
17650 return promise;
1766 }
17670 x = near[0];
17680 y = near[1];
1769 } else {
17700 if (near.type != "Point" || !Array.isArray(near.coordinates)) {
17710 promise.error(new Error("Must pass either a legacy coordinate array or GeoJSON Point to geoNear"));
17720 return promise;
1773 }
1774
17750 x = near.coordinates[0];
17760 y = near.coordinates[1];
1777 }
1778
17790 var self = this;
17800 this.collection.geoNear(x, y, options, function (err, res) {
17810 if (err) return promise.error(err);
17820 if (options.lean) return promise.fulfill(res.results, res.stats);
1783
17840 var count = res.results.length;
1785 // if there are no results, fulfill the promise now
17860 if (count == 0) {
17870 return promise.fulfill(res.results, res.stats);
1788 }
1789
17900 var errSeen = false;
17910 for (var i=0; i < res.results.length; i++) {
17920 var temp = res.results[i].obj;
17930 res.results[i].obj = new self();
17940 res.results[i].obj.init(temp, function (err) {
17950 if (err && !errSeen) {
17960 errSeen = true;
17970 return promise.error(err);
1798 }
17990 --count || promise.fulfill(res.results, res.stats);
1800 });
1801 }
1802 });
18030 return promise;
1804};
1805
1806/**
1807 * Performs [aggregations](http://docs.mongodb.org/manual/applications/aggregation/) on the models collection.
1808 *
1809 * If a `callback` is passed, the `aggregate` is executed and a `Promise` is returned. If a callback is not passed, the `aggregate` itself is returned.
1810 *
1811 * ####Example:
1812 *
1813 * // Find the max balance of all accounts
1814 * Users.aggregate(
1815 * { $group: { _id: null, maxBalance: { $max: '$balance' }}}
1816 * , { $project: { _id: 0, maxBalance: 1 }}
1817 * , function (err, res) {
1818 * if (err) return handleError(err);
1819 * console.log(res); // [ { maxBalance: 98000 } ]
1820 * });
1821 *
1822 * // Or use the aggregation pipeline builder.
1823 * Users.aggregate()
1824 * .group({ _id: null, maxBalance: { $max: '$balance' } })
1825 * .select('-id maxBalance')
1826 * .exec(function (err, res) {
1827 * if (err) return handleError(err);
1828 * console.log(res); // [ { maxBalance: 98 } ]
1829 * });
1830 *
1831 * ####NOTE:
1832 *
1833 * - Arguments are not cast to the model's schema because `$project` operators allow redefining the "shape" of the documents at any stage of the pipeline, which may leave documents in an incompatible format.
1834 * - The documents returned are plain javascript objects, not mongoose documents (since any shape of document can be returned).
1835 * - Requires MongoDB >= 2.1
1836 *
1837 * @see Aggregate #aggregate_Aggregate
1838 * @see MongoDB http://docs.mongodb.org/manual/applications/aggregation/
1839 * @param {Object|Array} [...] aggregation pipeline operator(s) or operator array
1840 * @param {Function} [callback]
1841 * @return {Aggregate|Promise}
1842 * @api public
1843 */
1844
18451Model.aggregate = function aggregate () {
18460 var args = [].slice.call(arguments)
1847 , aggregate
1848 , callback;
1849
18500 if ('function' === typeof args[args.length - 1]) {
18510 callback = args.pop();
1852 }
1853
18540 if (1 === args.length && util.isArray(args[0])) {
18550 aggregate = new Aggregate(args[0]);
1856 } else {
18570 aggregate = new Aggregate(args);
1858 }
1859
18600 aggregate.bind(this);
1861
18620 if ('undefined' === typeof callback) {
18630 return aggregate;
1864 }
1865
18660 return aggregate.exec(callback);
1867}
1868
1869/**
1870 * Implements `$geoSearch` functionality for Mongoose
1871 *
1872 * ####Example:
1873 *
1874 * var options = { near: [10, 10], maxDistance: 5 };
1875 * Locations.geoSearch({ type : "house" }, options, function(err, res) {
1876 * console.log(res);
1877 * });
1878 *
1879 * ####Options:
1880 * - `near` {Array} x,y point to search for
1881 * - `maxDistance` {Number} the maximum distance from the point near that a result can be
1882 * - `limit` {Number} The maximum number of results to return
1883 * - `lean` {Boolean} return the raw object instead of the Mongoose Model
1884 *
1885 * @param {Object} condition an object that specifies the match condition (required)
1886 * @param {Object} options for the geoSearch, some (near, maxDistance) are required
1887 * @param {Function} [callback] optional callback
1888 * @return {Promise}
1889 * @see http://docs.mongodb.org/manual/reference/command/geoSearch/
1890 * @see http://docs.mongodb.org/manual/core/geohaystack/
1891 * @api public
1892 */
1893
18941Model.geoSearch = function (conditions, options, callback) {
18950 if ('function' == typeof options) {
18960 callback = options;
18970 options = {};
1898 }
1899
19000 var promise = new Promise(callback);
1901
19020 if (conditions == undefined || !utils.isObject(conditions)) {
19030 return promise.error(new Error("Must pass conditions to geoSearch"));
1904 }
1905
19060 if (!options.near) {
19070 return promise.error(new Error("Must specify the near option in geoSearch"));
1908 }
1909
19100 if (!Array.isArray(options.near)) {
19110 return promise.error(new Error("near option must be an array [x, y]"));
1912 }
1913
1914
1915 // send the conditions in the options object
19160 options.search = conditions;
19170 var self = this;
1918
19190 this.collection.geoHaystackSearch(options.near[0], options.near[1], options, function (err, res) {
1920 // have to deal with driver problem. Should be fixed in a soon-ish release
1921 // (7/8/2013)
19220 if (err || res.errmsg) {
19230 if (!err) err = new Error(res.errmsg);
19240 if (res && res.code !== undefined) err.code = res.code;
19250 return promise.error(err);
1926 }
1927
19280 var count = res.results.length;
19290 if (options.lean || (count == 0)) return promise.fulfill(res.results, res.stats);
1930
19310 var errSeen = false;
19320 for (var i=0; i < res.results.length; i++) {
19330 var temp = res.results[i];
19340 res.results[i] = new self();
19350 res.results[i].init(temp, {}, function (err) {
19360 if (err && !errSeen) {
19370 errSeen = true;
19380 return promise.error(err);
1939 }
1940
19410 --count || (!errSeen && promise.fulfill(res.results, res.stats));
1942 });
1943 }
1944 });
1945
19460 return promise;
1947};
1948
1949/**
1950 * Populates document references.
1951 *
1952 * ####Available options:
1953 *
1954 * - path: space delimited path(s) to populate
1955 * - select: optional fields to select
1956 * - match: optional query conditions to match
1957 * - model: optional name of the model to use for population
1958 * - options: optional query options like sort, limit, etc
1959 *
1960 * ####Examples:
1961 *
1962 * // populates a single object
1963 * User.findById(id, function (err, user) {
1964 * var opts = [
1965 * { path: 'company', match: { x: 1 }, select: 'name' }
1966 * , { path: 'notes', options: { limit: 10 }, model: 'override' }
1967 * ]
1968 *
1969 * User.populate(user, opts, function (err, user) {
1970 * console.log(user);
1971 * })
1972 * })
1973 *
1974 * // populates an array of objects
1975 * User.find(match, function (err, users) {
1976 * var opts = [{ path: 'company', match: { x: 1 }, select: 'name' }]
1977 *
1978 * var promise = User.populate(users, opts);
1979 * promise.then(console.log).end();
1980 * })
1981 *
1982 * // imagine a Weapon model exists with two saved documents:
1983 * // { _id: 389, name: 'whip' }
1984 * // { _id: 8921, name: 'boomerang' }
1985 *
1986 * var user = { name: 'Indiana Jones', weapon: 389 }
1987 * Weapon.populate(user, { path: 'weapon', model: 'Weapon' }, function (err, user) {
1988 * console.log(user.weapon.name) // whip
1989 * })
1990 *
1991 * // populate many plain objects
1992 * var users = [{ name: 'Indiana Jones', weapon: 389 }]
1993 * users.push({ name: 'Batman', weapon: 8921 })
1994 * Weapon.populate(users, { path: 'weapon' }, function (err, users) {
1995 * users.forEach(function (user) {
1996 * console.log('%s uses a %s', users.name, user.weapon.name)
1997 * // Indiana Jones uses a whip
1998 * // Batman uses a boomerang
1999 * })
2000 * })
2001 * // Note that we didn't need to specify the Weapon model because
2002 * // we were already using it's populate() method.
2003 *
2004 * @param {Document|Array} docs Either a single document or array of documents to populate.
2005 * @param {Object} options A hash of key/val (path, options) used for population.
2006 * @param {Function} [cb(err,doc)] Optional callback, executed upon completion. Receives `err` and the `doc(s)`.
2007 * @return {Promise}
2008 * @api public
2009 */
2010
20111Model.populate = function (docs, paths, cb) {
20120 var promise = new Promise(cb);
2013
2014 // always resolve on nextTick for consistent async behavior
20150 function resolve () {
20160 var args = utils.args(arguments);
20170 process.nextTick(function () {
20180 promise.resolve.apply(promise, args);
2019 });
2020 }
2021
2022 // normalized paths
20230 var paths = utils.populate(paths);
20240 var pending = paths.length;
2025
20260 if (0 === pending) {
20270 resolve(null, docs);
20280 return promise;
2029 }
2030
2031 // each path has its own query options and must be executed separately
20320 var i = pending;
20330 var path;
20340 while (i--) {
20350 path = paths[i];
20360 populate(this, docs, path, next);
2037 }
2038
20390 return promise;
2040
20410 function next (err) {
20420 if (err) return resolve(err);
20430 if (--pending) return;
20440 resolve(null, docs);
2045 }
2046}
2047
2048/*!
2049 * Populates `docs`
2050 */
2051
20521function populate (model, docs, options, cb) {
20530 var select = options.select
2054 , match = options.match
2055 , path = options.path
2056
20570 var schema = model._getSchema(path);
20580 var subpath;
2059
2060 // handle document arrays
20610 if (schema && schema.caster) {
20620 schema = schema.caster;
2063 }
2064
2065 // model name for the populate query
20660 var modelName = options.model && options.model.modelName
2067 || options.model // query options
2068 || schema && schema.options.ref // declared in schema
2069 || model.modelName // an ad-hoc structure
2070
20710 var Model = model.db.model(modelName);
2072
2073 // expose the model used
20740 options.model = Model;
2075
2076 // normalize single / multiple docs passed
20770 if (!Array.isArray(docs)) {
20780 docs = [docs];
2079 }
2080
20810 if (0 === docs.length || docs.every(utils.isNullOrUndefined)) {
20820 return cb();
2083 }
2084
20850 var rawIds = [];
20860 var i, doc, id;
20870 var len = docs.length;
20880 var ret;
20890 var found = 0;
20900 var isDocument;
2091
20920 for (i = 0; i < len; i++) {
20930 ret = undefined;
20940 doc = docs[i];
20950 id = String(utils.getValue("_id", doc));
20960 isDocument = !! doc.$__;
2097
20980 if (isDocument && !doc.isModified(path)) {
2099 // it is possible a previously populated path is being
2100 // populated again. Because users can specify matcher
2101 // clauses in their populate arguments we use the cached
2102 // _ids from the original populate call to ensure all _ids
2103 // are looked up, but only if the path wasn't modified which
2104 // signifies the users intent of the state of the path.
21050 ret = doc.populated(path);
2106 }
2107
21080 if (!ret || Array.isArray(ret) && 0 === ret.length) {
21090 ret = utils.getValue(path, doc);
2110 }
2111
21120 if (ret) {
21130 ret = convertTo_id(ret);
2114
2115 // previously we always assigned this even if the document had no _id
21160 options._docs[id] = Array.isArray(ret)
2117 ? ret.slice()
2118 : ret;
2119 }
2120
2121 // always retain original values, even empty values. these are
2122 // used to map the query results back to the correct position.
21230 rawIds.push(ret);
2124
21250 if (isDocument) {
2126 // cache original populated _ids and model used
21270 doc.populated(path, options._docs[id], options);
2128 }
2129 }
2130
21310 var ids = utils.array.flatten(rawIds, function (item) {
2132 // no need to include undefined values in our query
21330 return undefined !== item;
2134 });
2135
21360 if (0 === ids.length || ids.every(utils.isNullOrUndefined)) {
21370 return cb();
2138 }
2139
2140 // preserve original match conditions by copying
21410 if (match) {
21420 match = utils.object.shallowCopy(match);
2143 } else {
21440 match = {};
2145 }
2146
21470 match._id || (match._id = { $in: ids });
2148
21490 var assignmentOpts = {};
21500 assignmentOpts.sort = options.options && options.options.sort || undefined;
21510 assignmentOpts.excludeId = /\s?-_id\s?/.test(select) || (select && 0 === select._id);
2152
21530 if (assignmentOpts.excludeId) {
2154 // override the exclusion from the query so we can use the _id
2155 // for document matching during assignment. we'll delete the
2156 // _id back off before returning the result.
21570 if ('string' == typeof select) {
21580 select = select.replace(/\s?-_id\s?/g, ' ');
2159 } else {
2160 // preserve original select conditions by copying
21610 select = utils.object.shallowCopy(select);
21620 delete select._id;
2163 }
2164 }
2165
2166 // if a limit option is passed, we should have the limit apply to *each*
2167 // document, not apply in the aggregate
21680 if (options.options && options.options.limit) {
21690 options.options.limit = options.options.limit * len;
2170 }
2171
21720 Model.find(match, select, options.options, function (err, vals) {
21730 if (err) return cb(err);
2174
21750 var lean = options.options && options.options.lean;
21760 var len = vals.length;
21770 var rawOrder = {};
21780 var rawDocs = {}
21790 var key;
21800 var val;
2181
2182 // optimization:
2183 // record the document positions as returned by
2184 // the query result.
21850 for (var i = 0; i < len; i++) {
21860 val = vals[i];
21870 key = String(utils.getValue('_id', val));
21880 rawDocs[key] = val;
21890 rawOrder[key] = i;
2190
2191 // flag each as result of population
21920 if (!lean) val.$__.wasPopulated = true;
2193 }
2194
21950 assignVals({
2196 rawIds: rawIds,
2197 rawDocs: rawDocs,
2198 rawOrder: rawOrder,
2199 docs: docs,
2200 path: path,
2201 options: assignmentOpts
2202 });
2203
22040 cb();
2205 });
2206}
2207
2208/*!
2209 * Retrieve the _id of `val` if a Document or Array of Documents.
2210 *
2211 * @param {Array|Document|Any} val
2212 * @return {Array|Document|Any}
2213 */
2214
22151function convertTo_id (val) {
22160 if (val instanceof Model) return val._id;
2217
22180 if (Array.isArray(val)) {
22190 for (var i = 0; i < val.length; ++i) {
22200 if (val[i] instanceof Model) {
22210 val[i] = val[i]._id;
2222 }
2223 }
22240 return val;
2225 }
2226
22270 return val;
2228}
2229
2230/*!
2231 * Assigns documents returned from a population query back
2232 * to the original document path.
2233 */
2234
22351function assignVals (o) {
2236 // replace the original ids in our intermediate _ids structure
2237 // with the documents found by query
2238
22390 assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, o.options);
2240
2241 // now update the original documents being populated using the
2242 // result structure that contains real documents.
2243
22440 var docs = o.docs;
22450 var path = o.path;
22460 var rawIds = o.rawIds;
22470 var options = o.options;
2248
22490 for (var i = 0; i < docs.length; ++i) {
22500 utils.setValue(path, rawIds[i], docs[i], function (val) {
22510 return valueFilter(val, options);
2252 });
2253 }
2254}
2255
2256/*!
2257 * 1) Apply backwards compatible find/findOne behavior to sub documents
2258 *
2259 * find logic:
2260 * a) filter out non-documents
2261 * b) remove _id from sub docs when user specified
2262 *
2263 * findOne
2264 * a) if no doc found, set to null
2265 * b) remove _id from sub docs when user specified
2266 *
2267 * 2) Remove _ids when specified by users query.
2268 *
2269 * background:
2270 * _ids are left in the query even when user excludes them so
2271 * that population mapping can occur.
2272 */
2273
22741function valueFilter (val, assignmentOpts) {
22750 if (Array.isArray(val)) {
2276 // find logic
22770 var ret = [];
22780 for (var i = 0; i < val.length; ++i) {
22790 var subdoc = val[i];
22800 if (!isDoc(subdoc)) continue;
22810 maybeRemoveId(subdoc, assignmentOpts);
22820 ret.push(subdoc);
2283 }
22840 return ret;
2285 }
2286
2287 // findOne
22880 if (isDoc(val)) {
22890 maybeRemoveId(val, assignmentOpts);
22900 return val;
2291 }
2292
22930 return null;
2294}
2295
2296/*!
2297 * Remove _id from `subdoc` if user specified "lean" query option
2298 */
2299
23001function maybeRemoveId (subdoc, assignmentOpts) {
23010 if (assignmentOpts.excludeId) {
23020 if ('function' == typeof subdoc.setValue) {
23030 subdoc.setValue('_id', undefined);
2304 } else {
23050 delete subdoc._id;
2306 }
2307 }
2308}
2309
2310/*!
2311 * Determine if `doc` is a document returned
2312 * by a populate query.
2313 */
2314
23151function isDoc (doc) {
23160 if (null == doc)
23170 return false;
2318
23190 var type = typeof doc;
23200 if ('string' == type)
23210 return false;
2322
23230 if ('number' == type)
23240 return false;
2325
23260 if (Buffer.isBuffer(doc))
23270 return false;
2328
23290 if ('ObjectID' == doc.constructor.name)
23300 return false;
2331
2332 // only docs
23330 return true;
2334}
2335
2336/*!
2337 * Assign `vals` returned by mongo query to the `rawIds`
2338 * structure returned from utils.getVals() honoring
2339 * query sort order if specified by user.
2340 *
2341 * This can be optimized.
2342 *
2343 * Rules:
2344 *
2345 * if the value of the path is not an array, use findOne rules, else find.
2346 * for findOne the results are assigned directly to doc path (including null results).
2347 * for find, if user specified sort order, results are assigned directly
2348 * else documents are put back in original order of array if found in results
2349 *
2350 * @param {Array} rawIds
2351 * @param {Array} vals
2352 * @param {Boolean} sort
2353 * @api private
2354 */
2355
23561function assignRawDocsToIdStructure (rawIds, resultDocs, resultOrder, options, recursed) {
2357 // honor user specified sort order
23580 var newOrder = [];
23590 var sorting = options.sort && rawIds.length > 1;
23600 var found;
23610 var doc;
23620 var sid;
23630 var id;
2364
23650 for (var i = 0; i < rawIds.length; ++i) {
23660 id = rawIds[i];
2367
23680 if (Array.isArray(id)) {
2369 // handle [ [id0, id2], [id3] ]
23700 assignRawDocsToIdStructure(id, resultDocs, resultOrder, options, true);
23710 newOrder.push(id);
23720 continue;
2373 }
2374
23750 if (null === id && !sorting) {
2376 // keep nulls for findOne unless sorting, which always
2377 // removes them (backward compat)
23780 newOrder.push(id);
23790 continue;
2380 }
2381
23820 sid = String(id);
23830 found = false;
2384
23850 if (recursed) {
2386 // apply find behavior
2387
2388 // assign matching documents in original order unless sorting
23890 doc = resultDocs[sid];
23900 if (doc) {
23910 if (sorting) {
23920 newOrder[resultOrder[sid]] = doc;
2393 } else {
23940 newOrder.push(doc);
2395 }
2396 } else {
23970 newOrder.push(id);
2398 }
2399 } else {
2400 // apply findOne behavior - if document in results, assign, else assign null
24010 newOrder[i] = doc = resultDocs[sid] || null;
2402 }
2403 }
2404
24050 rawIds.length = 0;
24060 if (newOrder.length) {
2407 // reassign the documents based on corrected order
2408
2409 // forEach skips over sparse entries in arrays so we
2410 // can safely use this to our advantage dealing with sorted
2411 // result sets too.
24120 newOrder.forEach(function (doc, i) {
24130 rawIds[i] = doc;
2414 });
2415 }
2416}
2417
2418/**
2419 * Finds the schema for `path`. This is different than
2420 * calling `schema.path` as it also resolves paths with
2421 * positional selectors (something.$.another.$.path).
2422 *
2423 * @param {String} path
2424 * @return {Schema}
2425 * @api private
2426 */
2427
24281Model._getSchema = function _getSchema (path) {
24290 var schema = this.schema
2430 , pathschema = schema.path(path);
2431
24320 if (pathschema)
24330 return pathschema;
2434
2435 // look for arrays
24360 return (function search (parts, schema) {
24370 var p = parts.length + 1
2438 , foundschema
2439 , trypath
2440
24410 while (p--) {
24420 trypath = parts.slice(0, p).join('.');
24430 foundschema = schema.path(trypath);
24440 if (foundschema) {
24450 if (foundschema.caster) {
2446
2447 // array of Mixed?
24480 if (foundschema.caster instanceof Types.Mixed) {
24490 return foundschema.caster;
2450 }
2451
2452 // Now that we found the array, we need to check if there
2453 // are remaining document paths to look up for casting.
2454 // Also we need to handle array.$.path since schema.path
2455 // doesn't work for that.
2456 // If there is no foundschema.schema we are dealing with
2457 // a path like array.$
24580 if (p !== parts.length && foundschema.schema) {
24590 if ('$' === parts[p]) {
2460 // comments.$.comments.$.title
24610 return search(parts.slice(p+1), foundschema.schema);
2462 } else {
2463 // this is the last path of the selector
24640 return search(parts.slice(p), foundschema.schema);
2465 }
2466 }
2467 }
24680 return foundschema;
2469 }
2470 }
2471 })(path.split('.'), schema)
2472}
2473
2474/*!
2475 * Compiler utility.
2476 *
2477 * @param {String} name model name
2478 * @param {Schema} schema
2479 * @param {String} collectionName
2480 * @param {Connection} connection
2481 * @param {Mongoose} base mongoose instance
2482 */
2483
24841Model.compile = function compile (name, schema, collectionName, connection, base) {
24850 var versioningEnabled = false !== schema.options.versionKey;
2486
24870 if (versioningEnabled && !schema.paths[schema.options.versionKey]) {
2488 // add versioning to top level documents only
24890 var o = {};
24900 o[schema.options.versionKey] = Number;
24910 schema.add(o);
2492 }
2493
2494 // generate new class
24950 function model (doc, fields, skipId) {
24960 if (!(this instanceof model))
24970 return new model(doc, fields, skipId);
24980 Model.call(this, doc, fields, skipId);
2499 };
2500
25010 model.base = base;
25020 model.modelName = name;
25030 model.__proto__ = Model;
25040 model.prototype.__proto__ = Model.prototype;
25050 model.model = Model.prototype.model;
25060 model.db = model.prototype.db = connection;
25070 model.discriminators = model.prototype.discriminators = undefined;
2508
25090 model.prototype.$__setSchema(schema);
2510
25110 var collectionOptions = {
2512 bufferCommands: schema.options.bufferCommands
2513 , capped: schema.options.capped
2514 };
2515
25160 model.prototype.collection = connection.collection(
2517 collectionName
2518 , collectionOptions
2519 );
2520
2521 // apply methods
25220 for (var i in schema.methods)
25230 model.prototype[i] = schema.methods[i];
2524
2525 // apply statics
25260 for (var i in schema.statics)
25270 model[i] = schema.statics[i];
2528
25290 model.schema = model.prototype.schema;
25300 model.options = model.prototype.options;
25310 model.collection = model.prototype.collection;
2532
25330 return model;
2534};
2535
2536/*!
2537 * Subclass this model with `conn`, `schema`, and `collection` settings.
2538 *
2539 * @param {Connection} conn
2540 * @param {Schema} [schema]
2541 * @param {String} [collection]
2542 * @return {Model}
2543 */
2544
25451Model.__subclass = function subclass (conn, schema, collection) {
2546 // subclass model using this connection and collection name
25470 var model = this;
2548
25490 var Model = function Model (doc, fields, skipId) {
25500 if (!(this instanceof Model)) {
25510 return new Model(doc, fields, skipId);
2552 }
25530 model.call(this, doc, fields, skipId);
2554 }
2555
25560 Model.__proto__ = model;
25570 Model.prototype.__proto__ = model.prototype;
25580 Model.db = Model.prototype.db = conn;
2559
25600 var s = schema && 'string' != typeof schema
2561 ? schema
2562 : model.prototype.schema;
2563
25640 var options = s.options || {};
2565
25660 if (!collection) {
25670 collection = model.prototype.schema.get('collection')
2568 || utils.toCollectionName(model.modelName, options);
2569 }
2570
25710 var collectionOptions = {
2572 bufferCommands: s ? options.bufferCommands : true
2573 , capped: s && options.capped
2574 };
2575
25760 Model.prototype.collection = conn.collection(collection, collectionOptions);
25770 Model.collection = Model.prototype.collection;
25780 Model.init();
25790 return Model;
2580}
2581
2582/*!
2583 * Module exports.
2584 */
2585
25861module.exports = exports = Model;
2587

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/promise.js

70%
17
12
5
LineHitsSource
1
2/*!
3 * Module dependencies
4 */
5
61var MPromise = require('mpromise');
7
8/**
9 * Promise constructor.
10 *
11 * Promises are returned from executed queries. Example:
12 *
13 * var query = Candy.find({ bar: true });
14 * var promise = query.exec();
15 *
16 * @param {Function} fn a function which will be called when the promise is resolved that accepts `fn(err, ...){}` as signature
17 * @inherits mpromise https://github.com/aheckmann/mpromise
18 * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
19 * @event `err`: Emits when the promise is rejected
20 * @event `complete`: Emits when the promise is fulfilled
21 * @api public
22 */
23
241function Promise (fn) {
250 MPromise.call(this, fn);
26}
27
28/*!
29 * Inherit from mpromise
30 */
31
321Promise.prototype = Object.create(MPromise.prototype, {
33 constructor: {
34 value: Promise
35 , enumerable: false
36 , writable: true
37 , configurable: true
38 }
39});
40
41/*!
42 * Override event names for backward compatibility.
43 */
44
451Promise.SUCCESS = 'complete';
461Promise.FAILURE = 'err';
47
48/**
49 * Adds `listener` to the `event`.
50 *
51 * If `event` is either the success or failure event and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event.
52 *
53 * @see mpromise#on https://github.com/aheckmann/mpromise#on
54 * @method on
55 * @memberOf Promise
56 * @param {String} event
57 * @param {Function} listener
58 * @return {Promise} this
59 * @api public
60 */
61
62/**
63 * Rejects this promise with `reason`.
64 *
65 * If the promise has already been fulfilled or rejected, not action is taken.
66 *
67 * @see mpromise#reject https://github.com/aheckmann/mpromise#reject
68 * @method reject
69 * @memberOf Promise
70 * @param {Object|String|Error} reason
71 * @return {Promise} this
72 * @api public
73 */
74
75/**
76 * Rejects this promise with `err`.
77 *
78 * If the promise has already been fulfilled or rejected, not action is taken.
79 *
80 * Differs from [#reject](#promise_Promise-reject) by first casting `err` to an `Error` if it is not `instanceof Error`.
81 *
82 * @api public
83 * @param {Error|String} err
84 * @return {Promise} this
85 */
86
871Promise.prototype.error = function (err) {
880 if (!(err instanceof Error)) err = new Error(err);
890 return this.reject(err);
90}
91
92/**
93 * Resolves this promise to a rejected state if `err` is passed or a fulfilled state if no `err` is passed.
94 *
95 * If the promise has already been fulfilled or rejected, not action is taken.
96 *
97 * `err` will be cast to an Error if not already instanceof Error.
98 *
99 * _NOTE: overrides [mpromise#resolve](https://github.com/aheckmann/mpromise#resolve) to provide error casting._
100 *
101 * @param {Error} [err] error or null
102 * @param {Object} [val] value to fulfill the promise with
103 * @api public
104 */
105
1061Promise.prototype.resolve = function (err, val) {
1070 if (err) return this.error(err);
1080 return this.fulfill(val);
109}
110
111/**
112 * Adds a single function as a listener to both err and complete.
113 *
114 * It will be executed with traditional node.js argument position when the promise is resolved.
115 *
116 * promise.addBack(function (err, args...) {
117 * if (err) return handleError(err);
118 * console.log('success');
119 * })
120 *
121 * Alias of [mpromise#onResolve](https://github.com/aheckmann/mpromise#onresolve).
122 *
123 * _Deprecated. Use `onResolve` instead._
124 *
125 * @method addBack
126 * @param {Function} listener
127 * @return {Promise} this
128 * @deprecated
129 */
130
1311Promise.prototype.addBack = Promise.prototype.onResolve;
132
133/**
134 * Fulfills this promise with passed arguments.
135 *
136 * @method fulfill
137 * @see https://github.com/aheckmann/mpromise#fulfill
138 * @param {any} args
139 * @api public
140 */
141
142/**
143 * Fulfills this promise with passed arguments.
144 *
145 * @method fulfill
146 * @see https://github.com/aheckmann/mpromise#fulfill
147 * @param {any} args
148 * @api public
149 */
150
151/**
152 * Fulfills this promise with passed arguments.
153 *
154 * Alias of [mpromise#fulfill](https://github.com/aheckmann/mpromise#fulfill).
155 *
156 * _Deprecated. Use `fulfill` instead._
157 *
158 * @method complete
159 * @param {any} args
160 * @api public
161 * @deprecated
162 */
163
1641Promise.prototype.complete = MPromise.prototype.fulfill;
165
166/**
167 * Adds a listener to the `complete` (success) event.
168 *
169 * Alias of [mpromise#onFulfill](https://github.com/aheckmann/mpromise#onfulfill).
170 *
171 * _Deprecated. Use `onFulfill` instead._
172 *
173 * @method addCallback
174 * @param {Function} listener
175 * @return {Promise} this
176 * @api public
177 * @deprecated
178 */
179
1801Promise.prototype.addCallback = Promise.prototype.onFulfill;
181
182/**
183 * Adds a listener to the `err` (rejected) event.
184 *
185 * Alias of [mpromise#onReject](https://github.com/aheckmann/mpromise#onreject).
186 *
187 * _Deprecated. Use `onReject` instead._
188 *
189 * @method addErrback
190 * @param {Function} listener
191 * @return {Promise} this
192 * @api public
193 * @deprecated
194 */
195
1961Promise.prototype.addErrback = Promise.prototype.onReject;
197
198/**
199 * Creates a new promise and returns it. If `onFulfill` or `onReject` are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick.
200 *
201 * Conforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification.
202 *
203 * ####Example:
204 *
205 * var promise = Meetups.find({ tags: 'javascript' }).select('_id').exec();
206 * promise.then(function (meetups) {
207 * var ids = meetups.map(function (m) {
208 * return m._id;
209 * });
210 * return People.find({ meetups: { $in: ids }).exec();
211 * }).then(function (people) {
212 * if (people.length < 10000) {
213 * throw new Error('Too few people!!!');
214 * } else {
215 * throw new Error('Still need more people!!!');
216 * }
217 * }).then(null, function (err) {
218 * assert.ok(err instanceof Error);
219 * });
220 *
221 * @see promises-A+ https://github.com/promises-aplus/promises-spec
222 * @see mpromise#then https://github.com/aheckmann/mpromise#then
223 * @method then
224 * @memberOf Promise
225 * @param {Function} onFulFill
226 * @param {Function} onReject
227 * @return {Promise} newPromise
228 */
229
230/**
231 * Signifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught.
232 *
233 * ####Example:
234 *
235 * var p = new Promise;
236 * p.then(function(){ throw new Error('shucks') });
237 * setTimeout(function () {
238 * p.fulfill();
239 * // error was caught and swallowed by the promise returned from
240 * // p.then(). we either have to always register handlers on
241 * // the returned promises or we can do the following...
242 * }, 10);
243 *
244 * // this time we use .end() which prevents catching thrown errors
245 * var p = new Promise;
246 * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <--
247 * setTimeout(function () {
248 * p.fulfill(); // throws "shucks"
249 * }, 10);
250 *
251 * @api public
252 * @see mpromise#end https://github.com/aheckmann/mpromise#end
253 * @method end
254 * @memberOf Promise
255 */
256
257/*!
258 * expose
259 */
260
2611module.exports = Promise;
262

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/query.js

8%
669
57
612
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var mquery = require('mquery');
61var util = require('util');
71var events = require('events');
81var mongo = require('mongodb');
9
101var utils = require('./utils');
111var Promise = require('./promise');
121var helpers = require('./queryhelpers');
131var Types = require('./schema/index');
141var Document = require('./document');
151var QueryStream = require('./querystream');
16
17/**
18 * Query constructor used for building queries.
19 *
20 * ####Example:
21 *
22 * var query = new Query();
23 * query.setOptions({ lean : true });
24 * query.collection(model.collection);
25 * query.where('age').gte(21).exec(callback);
26 *
27 * @param {Object} [options]
28 * @param {Object} [model]
29 * @param {Object} [conditions]
30 * @param {Object} [collection] Mongoose collection
31 * @api private
32 */
33
341function Query(conditions, options, model, collection) {
35 // this stuff is for dealing with custom queries created by #toConstructor
360 if (!this._mongooseOptions) {
370 this._mongooseOptions = options || {};
38 } else {
39 // this is the case where we have a CustomQuery, we need to check if we got
40 // options passed in, and if we did, merge them in
41
420 if (options) {
430 var keys = Object.keys(options);
440 for (var i=0; i < keys.length; i++) {
450 var k = keys[i];
460 this._mongooseOptions[k] = options[k];
47 }
48 }
49 }
50
510 if (collection) {
520 this.mongooseCollection = collection;
53 }
54
550 if (model) {
560 this.model = model;
57 }
58
59 // this is needed because map reduce returns a model that can be queried, but
60 // all of the queries on said model should be lean
610 if (this.model && this.model._mapreduce) {
620 this.lean();
63 }
64
65 // inherit mquery
660 mquery.call(this, this.mongooseCollection, options);
67
680 if (conditions) {
690 this.find(conditions);
70 }
71}
72
73/*!
74 * inherit mquery
75 */
76
771Query.prototype = new mquery;
781Query.prototype.constructor = Query;
791Query.base = mquery.prototype;
80
81/**
82 * Flag to opt out of using `$geoWithin`.
83 *
84 * mongoose.Query.use$geoWithin = false;
85 *
86 * MongoDB 2.4 deprecated the use of `$within`, replacing it with `$geoWithin`. Mongoose uses `$geoWithin` by default (which is 100% backward compatible with $within). If you are running an older version of MongoDB, set this flag to `false` so your `within()` queries continue to work.
87 *
88 * @see http://docs.mongodb.org/manual/reference/operator/geoWithin/
89 * @default true
90 * @property use$geoWithin
91 * @memberOf Query
92 * @receiver Query
93 * @api public
94 */
95
961Query.use$geoWithin = mquery.use$geoWithin;
97
98/**
99 * Converts this query to a customized, reusable query constructor with all arguments and options retained.
100 *
101 * ####Example
102 *
103 * // Create a query for adventure movies and read from the primary
104 * // node in the replica-set unless it is down, in which case we'll
105 * // read from a secondary node.
106 * var query = Movie.find({ tags: 'adventure' }).read('primaryPreferred');
107 *
108 * // create a custom Query constructor based off these settings
109 * var Adventure = query.toConstructor();
110 *
111 * // Adventure is now a subclass of mongoose.Query and works the same way but with the
112 * // default query parameters and options set.
113 * Adventure().exec(callback)
114 *
115 * // further narrow down our query results while still using the previous settings
116 * Adventure().where({ name: /^Life/ }).exec(callback);
117 *
118 * // since Adventure is a stand-alone constructor we can also add our own
119 * // helper methods and getters without impacting global queries
120 * Adventure.prototype.startsWith = function (prefix) {
121 * this.where({ name: new RegExp('^' + prefix) })
122 * return this;
123 * }
124 * Object.defineProperty(Adventure.prototype, 'highlyRated', {
125 * get: function () {
126 * this.where({ rating: { $gt: 4.5 }});
127 * return this;
128 * }
129 * })
130 * Adventure().highlyRated.startsWith('Life').exec(callback)
131 *
132 * New in 3.7.3
133 *
134 * @return {Query} subclass-of-Query
135 * @api public
136 */
137
1381Query.prototype.toConstructor = function toConstructor () {
1390 function CustomQuery (criteria, options) {
1400 if (!(this instanceof CustomQuery))
1410 return new CustomQuery(criteria, options);
1420 Query.call(this, criteria, options || null);
143 }
144
1450 util.inherits(CustomQuery, Query);
146
147 // set inherited defaults
1480 var p = CustomQuery.prototype;
149
1500 p.options = {};
151
1520 p.setOptions(this.options);
153
1540 p.op = this.op;
1550 p._conditions = utils.clone(this._conditions);
1560 p._fields = utils.clone(this._fields);
1570 p._update = utils.clone(this._update);
1580 p._path = this._path;
1590 p._distict = this._distinct;
1600 p._collection = this._collection;
1610 p.model = this.model;
1620 p.mongooseCollection = this.mongooseCollection;
1630 p._mongooseOptions = this._mongooseOptions;
164
1650 return CustomQuery;
166}
167
168/**
169 * Specifies a javascript function or expression to pass to MongoDBs query system.
170 *
171 * ####Example
172 *
173 * query.$where('this.comments.length > 10 || this.name.length > 5')
174 *
175 * // or
176 *
177 * query.$where(function () {
178 * return this.comments.length > 10 || this.name.length > 5;
179 * })
180 *
181 * ####NOTE:
182 *
183 * Only use `$where` when you have a condition that cannot be met using other MongoDB operators like `$lt`.
184 * **Be sure to read about all of [its caveats](http://docs.mongodb.org/manual/reference/operator/where/) before using.**
185 *
186 * @see $where http://docs.mongodb.org/manual/reference/operator/where/
187 * @method $where
188 * @param {String|Function} js javascript string or function
189 * @return {Query} this
190 * @memberOf Query
191 * @method $where
192 * @api public
193 */
194
195/**
196 * Specifies a `path` for use with chaining.
197 *
198 * ####Example
199 *
200 * // instead of writing:
201 * User.find({age: {$gte: 21, $lte: 65}}, callback);
202 *
203 * // we can instead write:
204 * User.where('age').gte(21).lte(65);
205 *
206 * // passing query conditions is permitted
207 * User.find().where({ name: 'vonderful' })
208 *
209 * // chaining
210 * User
211 * .where('age').gte(21).lte(65)
212 * .where('name', /^vonderful/i)
213 * .where('friends').slice(10)
214 * .exec(callback)
215 *
216 * @method where
217 * @memberOf Query
218 * @param {String|Object} [path]
219 * @param {any} [val]
220 * @return {Query} this
221 * @api public
222 */
223
224/**
225 * Specifies the complementary comparison value for paths specified with `where()`
226 *
227 * ####Example
228 *
229 * User.where('age').equals(49);
230 *
231 * // is the same as
232 *
233 * User.where('age', 49);
234 *
235 * @method equals
236 * @memberOf Query
237 * @param {Object} val
238 * @return {Query} this
239 * @api public
240 */
241
242/**
243 * Specifies arguments for an `$or` condition.
244 *
245 * ####Example
246 *
247 * query.or([{ color: 'red' }, { status: 'emergency' }])
248 *
249 * @see $or http://docs.mongodb.org/manual/reference/operator/or/
250 * @method or
251 * @memberOf Query
252 * @param {Array} array array of conditions
253 * @return {Query} this
254 * @api public
255 */
256
257/**
258 * Specifies arguments for a `$nor` condition.
259 *
260 * ####Example
261 *
262 * query.nor([{ color: 'green' }, { status: 'ok' }])
263 *
264 * @see $nor http://docs.mongodb.org/manual/reference/operator/nor/
265 * @method nor
266 * @memberOf Query
267 * @param {Array} array array of conditions
268 * @return {Query} this
269 * @api public
270 */
271
272/**
273 * Specifies arguments for a `$and` condition.
274 *
275 * ####Example
276 *
277 * query.and([{ color: 'green' }, { status: 'ok' }])
278 *
279 * @method and
280 * @memberOf Query
281 * @see $and http://docs.mongodb.org/manual/reference/operator/and/
282 * @param {Array} array array of conditions
283 * @return {Query} this
284 * @api public
285 */
286
287/**
288 * Specifies a $gt query condition.
289 *
290 * When called with one argument, the most recent path passed to `where()` is used.
291 *
292 * ####Example
293 *
294 * Thing.find().where('age').gt(21)
295 *
296 * // or
297 * Thing.find().gt('age', 21)
298 *
299 * @method gt
300 * @memberOf Query
301 * @param {String} [path]
302 * @param {Number} val
303 * @see $gt http://docs.mongodb.org/manual/reference/operator/gt/
304 * @api public
305 */
306
307/**
308 * Specifies a $gte query condition.
309 *
310 * When called with one argument, the most recent path passed to `where()` is used.
311 *
312 * @method gte
313 * @memberOf Query
314 * @param {String} [path]
315 * @param {Number} val
316 * @see $gte http://docs.mongodb.org/manual/reference/operator/gte/
317 * @api public
318 */
319
320/**
321 * Specifies a $lt query condition.
322 *
323 * When called with one argument, the most recent path passed to `where()` is used.
324 *
325 * @method lt
326 * @memberOf Query
327 * @param {String} [path]
328 * @param {Number} val
329 * @see $lt http://docs.mongodb.org/manual/reference/operator/lt/
330 * @api public
331 */
332
333/**
334 * Specifies a $lte query condition.
335 *
336 * When called with one argument, the most recent path passed to `where()` is used.
337 *
338 * @method lte
339 * @see $lte http://docs.mongodb.org/manual/reference/operator/lte/
340 * @memberOf Query
341 * @param {String} [path]
342 * @param {Number} val
343 * @api public
344 */
345
346/**
347 * Specifies a $ne query condition.
348 *
349 * When called with one argument, the most recent path passed to `where()` is used.
350 *
351 * @see $ne http://docs.mongodb.org/manual/reference/operator/ne/
352 * @method ne
353 * @memberOf Query
354 * @param {String} [path]
355 * @param {Number} val
356 * @api public
357 */
358
359/**
360 * Specifies an $in query condition.
361 *
362 * When called with one argument, the most recent path passed to `where()` is used.
363 *
364 * @see $in http://docs.mongodb.org/manual/reference/operator/in/
365 * @method in
366 * @memberOf Query
367 * @param {String} [path]
368 * @param {Number} val
369 * @api public
370 */
371
372/**
373 * Specifies an $nin query condition.
374 *
375 * When called with one argument, the most recent path passed to `where()` is used.
376 *
377 * @see $nin http://docs.mongodb.org/manual/reference/operator/nin/
378 * @method nin
379 * @memberOf Query
380 * @param {String} [path]
381 * @param {Number} val
382 * @api public
383 */
384
385/**
386 * Specifies an $all query condition.
387 *
388 * When called with one argument, the most recent path passed to `where()` is used.
389 *
390 * @see $all http://docs.mongodb.org/manual/reference/operator/all/
391 * @method all
392 * @memberOf Query
393 * @param {String} [path]
394 * @param {Number} val
395 * @api public
396 */
397
398/**
399 * Specifies a $size query condition.
400 *
401 * When called with one argument, the most recent path passed to `where()` is used.
402 *
403 * ####Example
404 *
405 * MyModel.where('tags').size(0).exec(function (err, docs) {
406 * if (err) return handleError(err);
407 *
408 * assert(Array.isArray(docs));
409 * console.log('documents with 0 tags', docs);
410 * })
411 *
412 * @see $size http://docs.mongodb.org/manual/reference/operator/size/
413 * @method size
414 * @memberOf Query
415 * @param {String} [path]
416 * @param {Number} val
417 * @api public
418 */
419
420/**
421 * Specifies a $regex query condition.
422 *
423 * When called with one argument, the most recent path passed to `where()` is used.
424 *
425 * @see $regex http://docs.mongodb.org/manual/reference/operator/regex/
426 * @method regex
427 * @memberOf Query
428 * @param {String} [path]
429 * @param {Number} val
430 * @api public
431 */
432
433/**
434 * Specifies a $maxDistance query condition.
435 *
436 * When called with one argument, the most recent path passed to `where()` is used.
437 *
438 * @see $maxDistance http://docs.mongodb.org/manual/reference/operator/maxDistance/
439 * @method maxDistance
440 * @memberOf Query
441 * @param {String} [path]
442 * @param {Number} val
443 * @api public
444 */
445
446/**
447 * Specifies a `$mod` condition
448 *
449 * @method mod
450 * @memberOf Query
451 * @param {String} [path]
452 * @param {Number} val
453 * @return {Query} this
454 * @see $mod http://docs.mongodb.org/manual/reference/operator/mod/
455 * @api public
456 */
457
458/**
459 * Specifies an `$exists` condition
460 *
461 * ####Example
462 *
463 * // { name: { $exists: true }}
464 * Thing.where('name').exists()
465 * Thing.where('name').exists(true)
466 * Thing.find().exists('name')
467 *
468 * // { name: { $exists: false }}
469 * Thing.where('name').exists(false);
470 * Thing.find().exists('name', false);
471 *
472 * @method exists
473 * @memberOf Query
474 * @param {String} [path]
475 * @param {Number} val
476 * @return {Query} this
477 * @see $exists http://docs.mongodb.org/manual/reference/operator/exists/
478 * @api public
479 */
480
481/**
482 * Specifies an `$elemMatch` condition
483 *
484 * ####Example
485 *
486 * query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
487 *
488 * query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
489 *
490 * query.elemMatch('comment', function (elem) {
491 * elem.where('author').equals('autobot');
492 * elem.where('votes').gte(5);
493 * })
494 *
495 * query.where('comment').elemMatch(function (elem) {
496 * elem.where({ author: 'autobot' });
497 * elem.where('votes').gte(5);
498 * })
499 *
500 * @method elemMatch
501 * @memberOf Query
502 * @param {String|Object|Function} path
503 * @param {Object|Function} criteria
504 * @return {Query} this
505 * @see $elemMatch http://docs.mongodb.org/manual/reference/operator/elemMatch/
506 * @api public
507 */
508
509/**
510 * Defines a `$within` or `$geoWithin` argument for geo-spatial queries.
511 *
512 * ####Example
513 *
514 * query.where(path).within().box()
515 * query.where(path).within().circle()
516 * query.where(path).within().geometry()
517 *
518 * query.where('loc').within({ center: [50,50], radius: 10, unique: true, spherical: true });
519 * query.where('loc').within({ box: [[40.73, -73.9], [40.7, -73.988]] });
520 * query.where('loc').within({ polygon: [[],[],[],[]] });
521 *
522 * query.where('loc').within([], [], []) // polygon
523 * query.where('loc').within([], []) // box
524 * query.where('loc').within({ type: 'LineString', coordinates: [...] }); // geometry
525 *
526 * **MUST** be used after `where()`.
527 *
528 * ####NOTE:
529 *
530 * As of Mongoose 3.7, `$geoWithin` is always used for queries. To change this behavior, see [Query.use$geoWithin](#query_Query-use%2524geoWithin).
531 *
532 * ####NOTE:
533 *
534 * In Mongoose 3.7, `within` changed from a getter to a function. If you need the old syntax, use [this](https://github.com/ebensing/mongoose-within).
535 *
536 * @method within
537 * @see $polygon http://docs.mongodb.org/manual/reference/operator/polygon/
538 * @see $box http://docs.mongodb.org/manual/reference/operator/box/
539 * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/
540 * @see $center http://docs.mongodb.org/manual/reference/operator/center/
541 * @see $centerSphere http://docs.mongodb.org/manual/reference/operator/centerSphere/
542 * @memberOf Query
543 * @return {Query} this
544 * @api public
545 */
546
547/**
548 * Specifies a $slice projection for an array.
549 *
550 * ####Example
551 *
552 * query.slice('comments', 5)
553 * query.slice('comments', -5)
554 * query.slice('comments', [10, 5])
555 * query.where('comments').slice(5)
556 * query.where('comments').slice([-10, 5])
557 *
558 * @method slice
559 * @memberOf Query
560 * @param {String} [path]
561 * @param {Number} val number/range of elements to slice
562 * @return {Query} this
563 * @see mongodb http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements
564 * @see $slice http://docs.mongodb.org/manual/reference/projection/slice/#prj._S_slice
565 * @api public
566 */
567
568/**
569 * Specifies the maximum number of documents the query will return.
570 *
571 * ####Example
572 *
573 * query.limit(20)
574 *
575 * ####Note
576 *
577 * Cannot be used with `distinct()`
578 *
579 * @method limit
580 * @memberOf Query
581 * @param {Number} val
582 * @api public
583 */
584
585/**
586 * Specifies the number of documents to skip.
587 *
588 * ####Example
589 *
590 * query.skip(100).limit(20)
591 *
592 * ####Note
593 *
594 * Cannot be used with `distinct()`
595 *
596 * @method skip
597 * @memberOf Query
598 * @param {Number} val
599 * @see cursor.skip http://docs.mongodb.org/manual/reference/method/cursor.skip/
600 * @api public
601 */
602
603/**
604 * Specifies the maxScan option.
605 *
606 * ####Example
607 *
608 * query.maxScan(100)
609 *
610 * ####Note
611 *
612 * Cannot be used with `distinct()`
613 *
614 * @method maxScan
615 * @memberOf Query
616 * @param {Number} val
617 * @see maxScan http://docs.mongodb.org/manual/reference/operator/maxScan/
618 * @api public
619 */
620
621/**
622 * Specifies the batchSize option.
623 *
624 * ####Example
625 *
626 * query.batchSize(100)
627 *
628 * ####Note
629 *
630 * Cannot be used with `distinct()`
631 *
632 * @method batchSize
633 * @memberOf Query
634 * @param {Number} val
635 * @see batchSize http://docs.mongodb.org/manual/reference/method/cursor.batchSize/
636 * @api public
637 */
638
639/**
640 * Specifies the `comment` option.
641 *
642 * ####Example
643 *
644 * query.comment('login query')
645 *
646 * ####Note
647 *
648 * Cannot be used with `distinct()`
649 *
650 * @method comment
651 * @memberOf Query
652 * @param {Number} val
653 * @see comment http://docs.mongodb.org/manual/reference/operator/comment/
654 * @api public
655 */
656
657/**
658 * Specifies this query as a `snapshot` query.
659 *
660 * ####Example
661 *
662 * query.snapshot() // true
663 * query.snapshot(true)
664 * query.snapshot(false)
665 *
666 * ####Note
667 *
668 * Cannot be used with `distinct()`
669 *
670 * @method snapshot
671 * @memberOf Query
672 * @see snapshot http://docs.mongodb.org/manual/reference/operator/snapshot/
673 * @return {Query} this
674 * @api public
675 */
676
677/**
678 * Sets query hints.
679 *
680 * ####Example
681 *
682 * query.hint({ indexA: 1, indexB: -1})
683 *
684 * ####Note
685 *
686 * Cannot be used with `distinct()`
687 *
688 * @method hint
689 * @memberOf Query
690 * @param {Object} val a hint object
691 * @return {Query} this
692 * @see $hint http://docs.mongodb.org/manual/reference/operator/hint/
693 * @api public
694 */
695
696/**
697 * Specifies which document fields to include or exclude
698 *
699 * When using string syntax, prefixing a path with `-` will flag that path as excluded. When a path does not have the `-` prefix, it is included. Lastly, if a path is prefixed with `+`, it forces inclusion of the path, which is useful for paths excluded at the [schema level](/docs/api.html#schematype_SchemaType-select).
700 *
701 * ####Example
702 *
703 * // include a and b, exclude c
704 * query.select('a b -c');
705 *
706 * // or you may use object notation, useful when
707 * // you have keys already prefixed with a "-"
708 * query.select({a: 1, b: 1, c: 0});
709 *
710 * // force inclusion of field excluded at schema level
711 * query.select('+path')
712 *
713 * ####NOTE:
714 *
715 * Cannot be used with `distinct()`.
716 *
717 * _v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3._
718 *
719 * @method select
720 * @memberOf Query
721 * @param {Object|String} arg
722 * @return {Query} this
723 * @see SchemaType
724 * @api public
725 */
726
727/**
728 * _DEPRECATED_ Sets the slaveOk option.
729 *
730 * **Deprecated** in MongoDB 2.2 in favor of [read preferences](#query_Query-read).
731 *
732 * ####Example:
733 *
734 * query.slaveOk() // true
735 * query.slaveOk(true)
736 * query.slaveOk(false)
737 *
738 * @method slaveOk
739 * @memberOf Query
740 * @deprecated use read() preferences instead if on mongodb >= 2.2
741 * @param {Boolean} v defaults to true
742 * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference
743 * @see slaveOk http://docs.mongodb.org/manual/reference/method/rs.slaveOk/
744 * @see read() #query_Query-read
745 * @return {Query} this
746 * @api public
747 */
748
749/**
750 * Determines the MongoDB nodes from which to read.
751 *
752 * ####Preferences:
753 *
754 * primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
755 * secondary Read from secondary if available, otherwise error.
756 * primaryPreferred Read from primary if available, otherwise a secondary.
757 * secondaryPreferred Read from a secondary if available, otherwise read from the primary.
758 * nearest All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
759 *
760 * Aliases
761 *
762 * p primary
763 * pp primaryPreferred
764 * s secondary
765 * sp secondaryPreferred
766 * n nearest
767 *
768 * ####Example:
769 *
770 * new Query().read('primary')
771 * new Query().read('p') // same as primary
772 *
773 * new Query().read('primaryPreferred')
774 * new Query().read('pp') // same as primaryPreferred
775 *
776 * new Query().read('secondary')
777 * new Query().read('s') // same as secondary
778 *
779 * new Query().read('secondaryPreferred')
780 * new Query().read('sp') // same as secondaryPreferred
781 *
782 * new Query().read('nearest')
783 * new Query().read('n') // same as nearest
784 *
785 * // read from secondaries with matching tags
786 * new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
787 *
788 * Read more about how to use read preferrences [here](http://docs.mongodb.org/manual/applications/replication/#read-preference) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences).
789 *
790 * @method read
791 * @memberOf Query
792 * @param {String} pref one of the listed preference options or aliases
793 * @param {Array} [tags] optional tags for this query
794 * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference
795 * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences
796 * @return {Query} this
797 * @api public
798 */
799
8001Query.prototype.read = function read (pref, tags) {
801 // first cast into a ReadPreference object to support tags
8020 var readPref = utils.readPref.apply(utils.readPref, arguments);
8030 return Query.base.read.call(this, readPref);
804}
805
806/**
807 * Merges another Query or conditions object into this one.
808 *
809 * When a Query is passed, conditions, field selection and options are merged.
810 *
811 * New in 3.7.0
812 *
813 * @method merge
814 * @memberOf Query
815 * @param {Query|Object} source
816 * @return {Query} this
817 */
818
819/**
820 * Sets query options.
821 *
822 * ####Options:
823 *
824 * - [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors) *
825 * - [sort](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsort(\)%7D%7D) *
826 * - [limit](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D) *
827 * - [skip](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D) *
828 * - [maxscan](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan) *
829 * - [batchSize](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D) *
830 * - [comment](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment) *
831 * - [snapshot](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D) *
832 * - [hint](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint) *
833 * - [slaveOk](http://docs.mongodb.org/manual/applications/replication/#read-preference) *
834 * - [lean](./api.html#query_Query-lean) *
835 * - [safe](http://www.mongodb.org/display/DOCS/getLastError+Command)
836 *
837 * _* denotes a query helper method is also available_
838 *
839 * @param {Object} options
840 * @api public
841 */
842
8431Query.prototype.setOptions = function (options, overwrite) {
844 // overwrite is only for internal use
8450 if (overwrite) {
846 // ensure that _mongooseOptions & options are two different objects
8470 this._mongooseOptions = (options && utils.clone(options)) || {};
8480 this.options = options || {};
849
8500 if('populate' in options) {
8510 this.populate(this._mongooseOptions);
852 }
8530 return this;
854 }
855
8560 if (!(options && 'Object' == options.constructor.name)) {
8570 return this;
858 }
859
8600 return Query.base.setOptions.call(this, options);
861}
862
863/**
864 * Returns fields selection for this query.
865 *
866 * @method _fieldsForExec
867 * @return {Object}
868 * @api private
869 */
870
871/**
872 * Return an update document with corrected $set operations.
873 *
874 * @method _updateForExec
875 * @api private
876 */
877
878/**
879 * Makes sure _path is set.
880 *
881 * @method _ensurePath
882 * @param {String} method
883 * @api private
884 */
885
886/**
887 * Determines if `conds` can be merged using `mquery().merge()`
888 *
889 * @method canMerge
890 * @memberOf Query
891 * @param {Object} conds
892 * @return {Boolean}
893 * @api private
894 */
895
896/**
897 * Returns default options for this query.
898 *
899 * @param {Model} model
900 * @api private
901 */
902
9031Query.prototype._optionsForExec = function (model) {
9040 var options = Query.base._optionsForExec.call(this);
905
9060 delete options.populate;
9070 model = model || this.model;
908
9090 if (!model) {
9100 return options;
911 } else {
9120 if (!('safe' in options) && model.schema.options.safe) {
9130 options.safe = model.schema.options.safe;
914 }
915
9160 if (!('readPreference' in options) && model.schema.options.read) {
9170 options.readPreference = model.schema.options.read;
918 }
919
9200 return options;
921 }
922};
923
924/**
925 * Sets the lean option.
926 *
927 * Documents returned from queries with the `lean` option enabled are plain javascript objects, not [MongooseDocuments](#document-js). They have no `save` method, getters/setters or other Mongoose magic applied.
928 *
929 * ####Example:
930 *
931 * new Query().lean() // true
932 * new Query().lean(true)
933 * new Query().lean(false)
934 *
935 * Model.find().lean().exec(function (err, docs) {
936 * docs[0] instanceof mongoose.Document // false
937 * });
938 *
939 * This is a [great](https://groups.google.com/forum/#!topic/mongoose-orm/u2_DzDydcnA/discussion) option in high-performance read-only scenarios, especially when combined with [stream](#query_Query-stream).
940 *
941 * @param {Boolean} bool defaults to true
942 * @return {Query} this
943 * @api public
944 */
945
9461Query.prototype.lean = function (v) {
9470 this._mongooseOptions.lean = arguments.length ? !!v : true;
9480 return this;
949}
950
951/**
952 * Finds documents.
953 *
954 * When no `callback` is passed, the query is not executed.
955 *
956 * ####Example
957 *
958 * query.find({ name: 'Los Pollos Hermanos' }).find(callback)
959 *
960 * @param {Object} [criteria] mongodb selector
961 * @param {Function} [callback]
962 * @return {Query} this
963 * @api public
964 */
965
9661Query.prototype.find = function (conditions, callback) {
9670 if ('function' == typeof conditions) {
9680 callback = conditions;
9690 conditions = {};
9700 } else if (conditions instanceof Document) {
9710 conditions = conditions.toObject();
972 }
973
9740 if (mquery.canMerge(conditions)) {
9750 this.merge(conditions);
976 }
977
9780 prepareDiscriminatorCriteria(this);
979
9800 try {
9810 this.cast(this.model);
9820 this._castError = null;
983 } catch (err) {
9840 this._castError = err;
985 }
986
987 // if we don't have a callback, then just return the query object
9880 if (!callback) {
9890 return Query.base.find.call(this);
990 }
991
9920 var promise = new Promise(callback);
9930 if (this._castError) {
9940 promise.error(this._castError);
9950 return this;
996 }
997
9980 this._applyPaths();
9990 this._fields = this._castFields(this._fields);
1000
10010 var fields = this._fieldsForExec();
10020 var options = this._mongooseOptions;
10030 var self = this;
1004
10050 return Query.base.find.call(this, {}, cb);
1006
10070 function cb(err, docs) {
10080 if (err) return promise.error(err);
1009
10100 if (0 === docs.length) {
10110 return promise.complete(docs);
1012 }
1013
10140 if (!options.populate) {
10150 return true === options.lean
1016 ? promise.complete(docs)
1017 : completeMany(self.model, docs, fields, self, null, promise);
1018 }
1019
10200 var pop = helpers.preparePopulationOptionsMQ(self, options);
10210 self.model.populate(docs, pop, function (err, docs) {
10220 if(err) return promise.error(err);
10230 return true === options.lean
1024 ? promise.complete(docs)
1025 : completeMany(self.model, docs, fields, self, pop, promise);
1026 });
1027 }
1028}
1029
1030/*!
1031 * hydrates many documents
1032 *
1033 * @param {Model} model
1034 * @param {Array} docs
1035 * @param {Object} fields
1036 * @param {Query} self
1037 * @param {Array} [pop] array of paths used in population
1038 * @param {Promise} promise
1039 */
1040
10411function completeMany (model, docs, fields, self, pop, promise) {
10420 var arr = [];
10430 var count = docs.length;
10440 var len = count;
10450 var opts = pop ?
1046 { populated: pop }
1047 : undefined;
10480 for (var i=0; i < len; ++i) {
10490 arr[i] = helpers.createModel(model, docs[i], fields);
10500 arr[i].init(docs[i], opts, function (err) {
10510 if (err) return promise.error(err);
10520 --count || promise.complete(arr);
1053 });
1054 }
1055}
1056
1057/**
1058 * Declares the query a findOne operation. When executed, the first found document is passed to the callback.
1059 *
1060 * Passing a `callback` executes the query.
1061 *
1062 * ####Example
1063 *
1064 * var query = Kitten.where({ color: 'white' });
1065 * query.findOne(function (err, kitten) {
1066 * if (err) return handleError(err);
1067 * if (kitten) {
1068 * // doc may be null if no document matched
1069 * }
1070 * });
1071 *
1072 * @param {Object|Query} [criteria] mongodb selector
1073 * @param {Function} [callback]
1074 * @return {Query} this
1075 * @see findOne http://docs.mongodb.org/manual/reference/method/db.collection.findOne/
1076 * @api public
1077 */
1078
10791Query.prototype.findOne = function (conditions, fields, options, callback) {
10800 if ('function' == typeof conditions) {
10810 callback = conditions;
10820 conditions = null;
10830 fields = null;
10840 options = null;
1085 }
1086
10870 if ('function' == typeof fields) {
10880 callback = fields;
10890 options = null;
10900 fields = null;
1091 }
1092
10930 if ('function' == typeof options) {
10940 callback = options;
10950 options = null;
1096 }
1097
1098 // make sure we don't send in the whole Document to merge()
10990 if (conditions instanceof Document) {
11000 conditions = conditions.toObject();
1101 }
1102
11030 if (options) {
11040 this.setOptions(options);
1105 }
1106
11070 if (fields) {
11080 this.select(fields);
1109 }
1110
11110 if (mquery.canMerge(conditions)) {
11120 this.merge(conditions);
1113 }
1114
11150 prepareDiscriminatorCriteria(this);
1116
11170 try {
11180 this.cast(this.model);
11190 this._castError = null;
1120 } catch (err) {
11210 this._castError = err;
1122 }
1123
11240 if (!callback) {
1125 // already merged in the conditions, don't need to send them in.
11260 return Query.base.findOne.call(this);
1127 }
1128
11290 var promise = new Promise(callback);
1130
11310 if (this._castError) {
11320 promise.error(this._castError);
11330 return this;
1134 }
1135
11360 this._applyPaths();
11370 this._fields = this._castFields(this._fields);
1138
11390 var options = this._mongooseOptions;
11400 var fields = this._fieldsForExec();
11410 var self = this;
1142
1143 // don't pass in the conditions because we already merged them in
11440 Query.base.findOne.call(this, {}, function cb (err, doc) {
11450 if (err) return promise.error(err);
11460 if (!doc) return promise.complete(null);
1147
11480 if (!options.populate) {
11490 return true === options.lean
1150 ? promise.complete(doc)
1151 : completeOne(self.model, doc, fields, self, null, promise);
1152 }
1153
11540 var pop = helpers.preparePopulationOptionsMQ(self, options);
11550 self.model.populate(doc, pop, function (err, doc) {
11560 if (err) return promise.error(err);
1157
11580 return true === options.lean
1159 ? promise.complete(doc)
1160 : completeOne(self.model, doc, fields, self, pop, promise);
1161 });
1162 })
1163
11640 return this;
1165}
1166
1167/**
1168 * Specifying this query as a `count` query.
1169 *
1170 * Passing a `callback` executes the query.
1171 *
1172 * ####Example:
1173 *
1174 * var countQuery = model.where({ 'color': 'black' }).count();
1175 *
1176 * query.count({ color: 'black' }).count(callback)
1177 *
1178 * query.count({ color: 'black' }, callback)
1179 *
1180 * query.where('color', 'black').count(function (err, count) {
1181 * if (err) return handleError(err);
1182 * console.log('there are %d kittens', count);
1183 * })
1184 *
1185 * @param {Object} [criteria] mongodb selector
1186 * @param {Function} [callback]
1187 * @return {Query} this
1188 * @see count http://docs.mongodb.org/manual/reference/method/db.collection.count/
1189 * @api public
1190 */
1191
11921Query.prototype.count = function (conditions, callback) {
11930 if ('function' == typeof conditions) {
11940 callback = conditions;
11950 conditions = undefined;
1196 }
1197
11980 if (mquery.canMerge(conditions)) {
11990 this.merge(conditions);
1200 }
1201
12020 try {
12030 this.cast(this.model);
1204 } catch (err) {
12050 callback(err);
12060 return this;
1207 }
1208
12090 return Query.base.count.call(this, {}, callback);
1210}
1211
1212/**
1213 * Declares or executes a distict() operation.
1214 *
1215 * Passing a `callback` executes the query.
1216 *
1217 * ####Example
1218 *
1219 * distinct(criteria, field, fn)
1220 * distinct(criteria, field)
1221 * distinct(field, fn)
1222 * distinct(field)
1223 * distinct(fn)
1224 * distinct()
1225 *
1226 * @param {Object|Query} [criteria]
1227 * @param {String} [field]
1228 * @param {Function} [callback]
1229 * @return {Query} this
1230 * @see distinct http://docs.mongodb.org/manual/reference/method/db.collection.distinct/
1231 * @api public
1232 */
1233
12341Query.prototype.distinct = function (conditions, field, callback) {
12350 if (!callback) {
12360 if('function' == typeof field) {
12370 callback = field;
12380 if ('string' == typeof conditions) {
12390 field = conditions;
12400 conditions = undefined;
1241 }
1242 }
1243
12440 switch (typeof conditions) {
1245 case 'string':
12460 field = conditions;
12470 conditions = undefined;
12480 break;
1249 case 'function':
12500 callback = conditions;
12510 field = undefined;
12520 conditions = undefined;
12530 break;
1254 }
1255 }
1256
12570 if (conditions instanceof Document) {
12580 conditions = conditions.toObject();
1259 }
1260
12610 if (mquery.canMerge(conditions)) {
12620 this.merge(conditions)
1263 }
1264
12650 try {
12660 this.cast(this.model);
1267 } catch (err) {
12680 callback(err);
12690 return this;
1270 }
1271
12720 return Query.base.distinct.call(this, {}, field, callback);
1273}
1274
1275/**
1276 * Sets the sort order
1277 *
1278 * If an object is passed, values allowed are `asc`, `desc`, `ascending`, `descending`, `1`, and `-1`.
1279 *
1280 * If a string is passed, it must be a space delimited list of path names. The
1281 * sort order of each path is ascending unless the path name is prefixed with `-`
1282 * which will be treated as descending.
1283 *
1284 * ####Example
1285 *
1286 * // sort by "field" ascending and "test" descending
1287 * query.sort({ field: 'asc', test: -1 });
1288 *
1289 * // equivalent
1290 * query.sort('field -test');
1291 *
1292 * ####Note
1293 *
1294 * Cannot be used with `distinct()`
1295 *
1296 * @param {Object|String} arg
1297 * @return {Query} this
1298 * @see cursor.sort http://docs.mongodb.org/manual/reference/method/cursor.sort/
1299 * @api public
1300 */
1301
13021Query.prototype.sort = function (arg) {
13030 var nArg = {};
1304
13050 if (arguments.length > 1) {
13060 throw new Error("sort() only takes 1 Argument");
1307 }
1308
13090 if (Array.isArray(arg)) {
1310 // time to deal with the terrible syntax
13110 for (var i=0; i < arg.length; i++) {
13120 if (!Array.isArray(arg[i])) throw new Error("Invalid sort() argument.");
13130 nArg[arg[i][0]] = arg[i][1];
1314 }
1315
1316 } else {
13170 nArg = arg;
1318 }
1319
13200 return Query.base.sort.call(this, nArg);
1321}
1322
1323/**
1324 * Declare and/or execute this query as a remove() operation.
1325 *
1326 * ####Example
1327 *
1328 * Model.remove({ artist: 'Anne Murray' }, callback)
1329 *
1330 * ####Note
1331 *
1332 * The operation is only executed when a callback is passed. To force execution without a callback (which would be an unsafe write), we must first call remove() and then execute it by using the `exec()` method.
1333 *
1334 * // not executed
1335 * var query = Model.find().remove({ name: 'Anne Murray' })
1336 *
1337 * // executed
1338 * query.remove({ name: 'Anne Murray' }, callback)
1339 * query.remove({ name: 'Anne Murray' }).remove(callback)
1340 *
1341 * // executed without a callback (unsafe write)
1342 * query.exec()
1343 *
1344 * // summary
1345 * query.remove(conds, fn); // executes
1346 * query.remove(conds)
1347 * query.remove(fn) // executes
1348 * query.remove()
1349 *
1350 * @param {Object|Query} [criteria] mongodb selector
1351 * @param {Function} [callback]
1352 * @return {Query} this
1353 * @see remove http://docs.mongodb.org/manual/reference/method/db.collection.remove/
1354 * @api public
1355 */
1356
13571Query.prototype.remove = function (cond, callback) {
13580 if ('function' == typeof cond) {
13590 callback = cond;
13600 cond = null;
1361 }
1362
13630 var cb = 'function' == typeof callback;
1364
13650 try {
13660 this.cast(this.model);
1367 } catch (err) {
13680 if (cb) return process.nextTick(callback.bind(null, err));
13690 return this;
1370 }
1371
13720 return Query.base.remove.call(this, cond, callback);
1373}
1374
1375/*!
1376 * hydrates a document
1377 *
1378 * @param {Model} model
1379 * @param {Document} doc
1380 * @param {Object} fields
1381 * @param {Query} self
1382 * @param {Array} [pop] array of paths used in population
1383 * @param {Promise} promise
1384 */
1385
13861function completeOne (model, doc, fields, self, pop, promise) {
13870 var opts = pop ?
1388 { populated: pop }
1389 : undefined;
1390
13910 var casted = helpers.createModel(model, doc, fields)
13920 casted.init(doc, opts, function (err) {
13930 if (err) return promise.error(err);
13940 promise.complete(casted);
1395 });
1396}
1397
1398/*!
1399 * If the model is a discriminator type and not root, then add the key & value to the criteria.
1400 */
1401
14021function prepareDiscriminatorCriteria(query) {
14030 if (!query || !query.model || !query.model.schema) {
14040 return;
1405 }
1406
14070 var schema = query.model.schema;
1408
14090 if (schema && schema.discriminatorMapping && !schema.discriminatorMapping.isRoot) {
14100 query._conditions[schema.discriminatorMapping.key] = schema.discriminatorMapping.value;
1411 }
1412}
1413
1414/**
1415 * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) update command.
1416 *
1417 * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed.
1418 *
1419 * ####Available options
1420 *
1421 * - `new`: bool - true to return the modified document rather than the original. defaults to true
1422 * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
1423 * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
1424 *
1425 * ####Examples
1426 *
1427 * query.findOneAndUpdate(conditions, update, options, callback) // executes
1428 * query.findOneAndUpdate(conditions, update, options) // returns Query
1429 * query.findOneAndUpdate(conditions, update, callback) // executes
1430 * query.findOneAndUpdate(conditions, update) // returns Query
1431 * query.findOneAndUpdate(update, callback) // returns Query
1432 * query.findOneAndUpdate(update) // returns Query
1433 * query.findOneAndUpdate(callback) // executes
1434 * query.findOneAndUpdate() // returns Query
1435 *
1436 * @method findOneAndUpdate
1437 * @memberOf Query
1438 * @param {Object|Query} [query]
1439 * @param {Object} [doc]
1440 * @param {Object} [options]
1441 * @param {Function} [callback]
1442 * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
1443 * @return {Query} this
1444 * @api public
1445 */
1446
1447/**
1448 * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) remove command.
1449 *
1450 * Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if `callback` is passed.
1451 *
1452 * ####Available options
1453 *
1454 * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
1455 *
1456 * ####Examples
1457 *
1458 * A.where().findOneAndRemove(conditions, options, callback) // executes
1459 * A.where().findOneAndRemove(conditions, options) // return Query
1460 * A.where().findOneAndRemove(conditions, callback) // executes
1461 * A.where().findOneAndRemove(conditions) // returns Query
1462 * A.where().findOneAndRemove(callback) // executes
1463 * A.where().findOneAndRemove() // returns Query
1464 *
1465 * @method findOneAndRemove
1466 * @memberOf Query
1467 * @param {Object} [conditions]
1468 * @param {Object} [options]
1469 * @param {Function} [callback]
1470 * @return {Query} this
1471 * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
1472 * @api public
1473 */
1474
1475/**
1476 * Override mquery.prototype._findAndModify to provide casting etc.
1477 *
1478 * @param {String} type - either "remove" or "update"
1479 * @param {Function} callback
1480 * @api private
1481 */
1482
14831Query.prototype._findAndModify = function (type, callback) {
14840 if ('function' != typeof callback) {
14850 throw new Error("Expected callback in _findAndModify");
1486 }
1487
14880 var model = this.model
1489 , promise = new Promise(callback)
1490 , self = this
1491 , castedQuery
1492 , castedDoc
1493 , fields
1494 , opts;
1495
14960 castedQuery = castQuery(this);
14970 if (castedQuery instanceof Error) {
14980 process.nextTick(promise.error.bind(promise, castedQuery));
14990 return promise;
1500 }
1501
15020 opts = this._optionsForExec(model);
1503
15040 if ('remove' == type) {
15050 opts.remove = true;
1506 } else {
15070 if (!('new' in opts)) opts.new = true;
15080 if (!('upsert' in opts)) opts.upsert = false;
1509
15100 castedDoc = castDoc(this, opts.overwrite);
15110 if (!castedDoc) {
15120 if (opts.upsert) {
1513 // still need to do the upsert to empty doc
15140 castedDoc = { $set: {} };
1515 } else {
15160 return this.findOne(callback);
1517 }
15180 } else if (castedDoc instanceof Error) {
15190 process.nextTick(promise.error.bind(promise, castedDoc));
15200 return promise;
1521 }
1522 }
1523
15240 this._applyPaths();
1525
15260 var self = this;
15270 var options = this._mongooseOptions;
1528
15290 if (this._fields) {
15300 fields = utils.clone(this._fields);
15310 opts.fields = this._castFields(fields);
15320 if (opts.fields instanceof Error) {
15330 process.nextTick(promise.error.bind(promise, opts.fields));
15340 return promise;
1535 }
1536 }
1537
15380 if (opts.sort) convertSortToArray(opts);
1539
15400 this._collection.findAndModify(castedQuery, castedDoc, opts, utils.tick(cb));
15410 function cb (err, doc) {
15420 if (err) return promise.error(err);
1543
15440 if (!doc || (utils.isObject(doc) && Object.keys(doc).length === 0)) {
15450 return promise.complete(null);
1546 }
1547
15480 if (!options.populate) {
15490 return true === options.lean
1550 ? promise.complete(doc)
1551 : completeOne(self.model, doc, fields, self, null, promise);
1552 }
1553
15540 var pop = helpers.preparePopulationOptionsMQ(self, options);
15550 self.model.populate(doc, pop, function (err, doc) {
15560 if (err) return promise.error(err);
1557
15580 return true === options.lean
1559 ? promise.complete(doc)
1560 : completeOne(self.model, doc, fields, self, pop, promise);
1561 });
1562 }
1563
15640 return promise;
1565}
1566
1567/*!
1568 * The mongodb driver 1.3.23 only supports the nested array sort
1569 * syntax. We must convert it or sorting findAndModify will not work.
1570 */
1571
15721function convertSortToArray (opts) {
15730 if (Array.isArray(opts.sort)) return;
15740 if (!utils.isObject(opts.sort)) return;
1575
15760 var sort = [];
1577
15780 for (var key in opts.sort) if (utils.object.hasOwnProperty(opts.sort, key)) {
15790 sort.push([ key, opts.sort[key] ]);
1580 }
1581
15820 opts.sort = sort;
1583}
1584
1585/**
1586 * Declare and/or execute this query as an update() operation.
1587 *
1588 * _All paths passed that are not $atomic operations will become $set ops._
1589 *
1590 * ####Example
1591 *
1592 * Model.where({ _id: id }).update({ title: 'words' })
1593 *
1594 * // becomes
1595 *
1596 * Model.where({ _id: id }).update({ $set: { title: 'words' }})
1597 *
1598 * ####Note
1599 *
1600 * Passing an empty object `{}` as the doc will result in a no-op unless the `overwrite` option is passed. Without the `overwrite` option set, the update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting documents in the collection.
1601 *
1602 * ####Note
1603 *
1604 * The operation is only executed when a callback is passed. To force execution without a callback (which would be an unsafe write), we must first call update() and then execute it by using the `exec()` method.
1605 *
1606 * var q = Model.where({ _id: id });
1607 * q.update({ $set: { name: 'bob' }}).update(); // not executed
1608 *
1609 * q.update({ $set: { name: 'bob' }}).exec(); // executed as unsafe
1610 *
1611 * // keys that are not $atomic ops become $set.
1612 * // this executes the same command as the previous example.
1613 * q.update({ name: 'bob' }).exec();
1614 *
1615 * // overwriting with empty docs
1616 * var q = Model.where({ _id: id }).setOptions({ overwrite: true })
1617 * q.update({ }, callback); // executes
1618 *
1619 * // multi update with overwrite to empty doc
1620 * var q = Model.where({ _id: id });
1621 * q.setOptions({ multi: true, overwrite: true })
1622 * q.update({ });
1623 * q.update(callback); // executed
1624 *
1625 * // multi updates
1626 * Model.where()
1627 * .update({ name: /^match/ }, { $set: { arr: [] }}, { multi: true }, callback)
1628 *
1629 * // more multi updates
1630 * Model.where()
1631 * .setOptions({ multi: true })
1632 * .update({ $set: { arr: [] }}, callback)
1633 *
1634 * // single update by default
1635 * Model.where({ email: 'address@example.com' })
1636 * .update({ $inc: { counter: 1 }}, callback)
1637 *
1638 * API summary
1639 *
1640 * update(criteria, doc, options, cb) // executes
1641 * update(criteria, doc, options)
1642 * update(criteria, doc, cb) // executes
1643 * update(criteria, doc)
1644 * update(doc, cb) // executes
1645 * update(doc)
1646 * update(cb) // executes
1647 * update(true) // executes (unsafe write)
1648 * update()
1649 *
1650 * @param {Object} [criteria]
1651 * @param {Object} [doc] the update command
1652 * @param {Object} [options]
1653 * @param {Function} [callback]
1654 * @return {Query} this
1655 * @see Model.update #model_Model.update
1656 * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/
1657 * @api public
1658 */
1659
16601Query.prototype.update = function (conditions, doc, options, callback) {
16610 if ('function' === typeof options) {
1662 // Scenario: update(conditions, doc, callback)
16630 callback = options;
16640 options = null;
16650 } else if ('function' === typeof doc) {
1666 // Scenario: update(doc, callback);
16670 callback = doc;
16680 doc = conditions;
16690 conditions = {};
16700 options = null;
16710 } else if ('function' === typeof conditions) {
16720 callback = conditions;
16730 conditions = undefined;
16740 doc = undefined;
16750 options = undefined;
1676 }
1677
1678 // make sure we don't send in the whole Document to merge()
16790 if (conditions instanceof Document) {
16800 conditions = conditions.toObject();
1681 }
1682
1683 // strict is an option used in the update checking, make sure it gets set
16840 if (options) {
16850 if ('strict' in options) {
16860 this._mongooseOptions.strict = options.strict;
1687 }
1688 }
1689
1690 // if doc is undefined at this point, this means this function is being
1691 // executed by exec(not always see below). Grab the update doc from here in
1692 // order to validate
1693 // This could also be somebody calling update() or update({}). Probably not a
1694 // common use case, check for _update to make sure we don't do anything bad
16950 if (!doc && this._update) {
16960 doc = this._updateForExec();
1697 }
1698
16990 if (conditions) {
17000 this._conditions = conditions;
1701 }
1702
1703 // validate the selector part of the query
17040 var castedQuery = castQuery(this);
17050 if (castedQuery instanceof Error) {
17060 if(callback) {
17070 callback(castedQuery);
17080 return this;
1709 } else {
17100 throw castedQuery;
1711 }
1712 }
1713
1714 // validate the update part of the query
17150 var castedDoc;
17160 try {
17170 castedDoc = this._castUpdate(doc, options && options.overwrite);
1718 } catch (err) {
17190 if (callback) {
17200 callback(err);
17210 return this;
1722 } else {
17230 throw err;
1724 }
1725 }
1726
17270 if (!castedDoc) {
17280 callback && callback(null, 0);
17290 return this;
1730 }
1731
17320 return Query.base.update.call(this, castedQuery, castedDoc, options, callback);
1733}
1734
1735/**
1736 * Executes the query
1737 *
1738 * ####Examples:
1739 *
1740 * var promise = query.exec();
1741 * var promise = query.exec('update');
1742 *
1743 * query.exec(callback);
1744 * query.exec('find', callback);
1745 *
1746 * @param {String|Function} [operation]
1747 * @param {Function} [callback]
1748 * @return {Promise}
1749 * @api public
1750 */
1751
17521Query.prototype.exec = function exec (op, callback) {
17530 var promise = new Promise();
1754
17550 if ('function' == typeof op) {
17560 callback = op;
17570 op = null;
17580 } else if ('string' == typeof op) {
17590 this.op = op;
1760 }
1761
17620 if (callback) promise.addBack(callback);
1763
17640 if (!this.op) {
17650 promise.complete();
17660 return promise;
1767 }
1768
17690 Query.base.exec.call(this, op, promise.resolve.bind(promise));
1770
17710 return promise;
1772}
1773
1774/**
1775 * Finds the schema for `path`. This is different than
1776 * calling `schema.path` as it also resolves paths with
1777 * positional selectors (something.$.another.$.path).
1778 *
1779 * @param {String} path
1780 * @api private
1781 */
1782
17831Query.prototype._getSchema = function _getSchema (path) {
17840 return this.model._getSchema(path);
1785}
1786
1787/*!
1788 * These operators require casting docs
1789 * to real Documents for Update operations.
1790 */
1791
17921var castOps = {
1793 $push: 1
1794 , $pushAll: 1
1795 , $addToSet: 1
1796 , $set: 1
1797};
1798
1799/*!
1800 * These operators should be cast to numbers instead
1801 * of their path schema type.
1802 */
1803
18041var numberOps = {
1805 $pop: 1
1806 , $unset: 1
1807 , $inc: 1
1808}
1809
1810/**
1811 * Casts obj for an update command.
1812 *
1813 * @param {Object} obj
1814 * @return {Object} obj after casting its values
1815 * @api private
1816 */
1817
18181Query.prototype._castUpdate = function _castUpdate (obj, overwrite) {
18190 if (!obj) return undefined;
1820
18210 var ops = Object.keys(obj)
1822 , i = ops.length
1823 , ret = {}
1824 , hasKeys
1825 , val
1826
18270 while (i--) {
18280 var op = ops[i];
1829 // if overwrite is set, don't do any of the special $set stuff
18300 if ('$' !== op[0] && !overwrite) {
1831 // fix up $set sugar
18320 if (!ret.$set) {
18330 if (obj.$set) {
18340 ret.$set = obj.$set;
1835 } else {
18360 ret.$set = {};
1837 }
1838 }
18390 ret.$set[op] = obj[op];
18400 ops.splice(i, 1);
18410 if (!~ops.indexOf('$set')) ops.push('$set');
18420 } else if ('$set' === op) {
18430 if (!ret.$set) {
18440 ret[op] = obj[op];
1845 }
1846 } else {
18470 ret[op] = obj[op];
1848 }
1849 }
1850
1851 // cast each value
18520 i = ops.length;
1853
1854 // if we get passed {} for the update, we still need to respect that when it
1855 // is an overwrite scenario
18560 if (overwrite) {
18570 hasKeys = true;
1858 }
1859
18600 while (i--) {
18610 op = ops[i];
18620 val = ret[op];
18630 if ('Object' === val.constructor.name && !overwrite) {
18640 hasKeys |= this._walkUpdatePath(val, op);
18650 } else if (overwrite && 'Object' === ret.constructor.name) {
1866 // if we are just using overwrite, cast the query and then we will
1867 // *always* return the value, even if it is an empty object. We need to
1868 // set hasKeys above because we need to account for the case where the
1869 // user passes {} and wants to clobber the whole document
1870 // Also, _walkUpdatePath expects an operation, so give it $set since that
1871 // is basically what we're doing
18720 this._walkUpdatePath(ret, '$set');
1873 } else {
18740 var msg = 'Invalid atomic update value for ' + op + '. '
1875 + 'Expected an object, received ' + typeof val;
18760 throw new Error(msg);
1877 }
1878 }
1879
18800 return hasKeys && ret;
1881}
1882
1883/**
1884 * Walk each path of obj and cast its values
1885 * according to its schema.
1886 *
1887 * @param {Object} obj - part of a query
1888 * @param {String} op - the atomic operator ($pull, $set, etc)
1889 * @param {String} pref - path prefix (internal only)
1890 * @return {Bool} true if this path has keys to update
1891 * @api private
1892 */
1893
18941Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
18950 var prefix = pref ? pref + '.' : ''
1896 , keys = Object.keys(obj)
1897 , i = keys.length
1898 , hasKeys = false
1899 , schema
1900 , key
1901 , val
1902
19030 var strict = 'strict' in this._mongooseOptions
1904 ? this._mongooseOptions.strict
1905 : this.model.schema.options.strict;
1906
19070 while (i--) {
19080 key = keys[i];
19090 val = obj[key];
1910
19110 if (val && 'Object' === val.constructor.name) {
1912 // watch for embedded doc schemas
19130 schema = this._getSchema(prefix + key);
19140 if (schema && schema.caster && op in castOps) {
1915 // embedded doc schema
1916
19170 if (strict && !schema) {
1918 // path is not in our strict schema
19190 if ('throw' == strict) {
19200 throw new Error('Field `' + key + '` is not in schema.');
1921 } else {
1922 // ignore paths not specified in schema
19230 delete obj[key];
1924 }
1925 } else {
19260 hasKeys = true;
1927
19280 if ('$each' in val) {
19290 obj[key] = {
1930 $each: this._castUpdateVal(schema, val.$each, op)
1931 }
1932
19330 if (val.$slice) {
19340 obj[key].$slice = val.$slice | 0;
1935 }
1936
19370 if (val.$sort) {
19380 obj[key].$sort = val.$sort;
1939 }
1940
1941 } else {
19420 obj[key] = this._castUpdateVal(schema, val, op);
1943 }
1944 }
1945 } else {
19460 hasKeys |= this._walkUpdatePath(val, op, prefix + key);
1947 }
1948 } else {
19490 schema = '$each' === key
1950 ? this._getSchema(pref)
1951 : this._getSchema(prefix + key);
1952
19530 var skip = strict &&
1954 !schema &&
1955 !/real|nested/.test(this.model.schema.pathType(prefix + key));
1956
19570 if (skip) {
19580 if ('throw' == strict) {
19590 throw new Error('Field `' + prefix + key + '` is not in schema.');
1960 } else {
19610 delete obj[key];
1962 }
1963 } else {
19640 hasKeys = true;
19650 obj[key] = this._castUpdateVal(schema, val, op, key);
1966 }
1967 }
1968 }
19690 return hasKeys;
1970}
1971
1972/**
1973 * Casts `val` according to `schema` and atomic `op`.
1974 *
1975 * @param {Schema} schema
1976 * @param {Object} val
1977 * @param {String} op - the atomic operator ($pull, $set, etc)
1978 * @param {String} [$conditional]
1979 * @api private
1980 */
1981
19821Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
19830 if (!schema) {
1984 // non-existing schema path
19850 return op in numberOps
1986 ? Number(val)
1987 : val
1988 }
1989
19900 if (schema.caster && op in castOps &&
1991 (utils.isObject(val) || Array.isArray(val))) {
1992 // Cast values for ops that add data to MongoDB.
1993 // Ensures embedded documents get ObjectIds etc.
19940 var tmp = schema.cast(val);
1995
19960 if (Array.isArray(val)) {
19970 val = tmp;
1998 } else {
19990 val = tmp[0];
2000 }
2001 }
2002
20030 if (op in numberOps) return Number(val);
20040 if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
20050 return schema.castForQuery(val)
2006}
2007
2008/*!
2009 * castQuery
2010 * @api private
2011 */
2012
20131function castQuery (query) {
20140 try {
20150 return query.cast(query.model);
2016 } catch (err) {
20170 return err;
2018 }
2019}
2020
2021/*!
2022 * castDoc
2023 * @api private
2024 */
2025
20261function castDoc (query, overwrite) {
20270 try {
20280 return query._castUpdate(query._update, overwrite);
2029 } catch (err) {
20300 return err;
2031 }
2032}
2033
2034/**
2035 * Specifies paths which should be populated with other documents.
2036 *
2037 * ####Example:
2038 *
2039 * Kitten.findOne().populate('owner').exec(function (err, kitten) {
2040 * console.log(kitten.owner.name) // Max
2041 * })
2042 *
2043 * Kitten.find().populate({
2044 * path: 'owner'
2045 * , select: 'name'
2046 * , match: { color: 'black' }
2047 * , options: { sort: { name: -1 }}
2048 * }).exec(function (err, kittens) {
2049 * console.log(kittens[0].owner.name) // Zoopa
2050 * })
2051 *
2052 * // alternatively
2053 * Kitten.find().populate('owner', 'name', null, {sort: { name: -1 }}).exec(function (err, kittens) {
2054 * console.log(kittens[0].owner.name) // Zoopa
2055 * })
2056 *
2057 * Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.
2058 *
2059 * @param {Object|String} path either the path to populate or an object specifying all parameters
2060 * @param {Object|String} [select] Field selection for the population query
2061 * @param {Model} [model] The name of the model you wish to use for population. If not specified, the name is looked up from the Schema ref.
2062 * @param {Object} [match] Conditions for the population query
2063 * @param {Object} [options] Options for the population query (sort, etc)
2064 * @see population ./populate.html
2065 * @see Query#select #query_Query-select
2066 * @see Model.populate #model_Model.populate
2067 * @return {Query} this
2068 * @api public
2069 */
2070
20711Query.prototype.populate = function () {
20720 var res = utils.populate.apply(null, arguments);
20730 var opts = this._mongooseOptions;
2074
20750 if (!utils.isObject(opts.populate)) {
20760 opts.populate = {};
2077 }
2078
20790 for (var i = 0; i < res.length; ++i) {
20800 opts.populate[res[i].path] = res[i];
2081 }
2082
20830 return this;
2084}
2085
2086/**
2087 * Casts this query to the schema of `model`
2088 *
2089 * ####Note
2090 *
2091 * If `obj` is present, it is cast instead of this query.
2092 *
2093 * @param {Model} model
2094 * @param {Object} [obj]
2095 * @return {Object}
2096 * @api public
2097 */
2098
20991Query.prototype.cast = function (model, obj) {
21000 obj || (obj = this._conditions);
2101
21020 var schema = model.schema
2103 , paths = Object.keys(obj)
2104 , i = paths.length
2105 , any$conditionals
2106 , schematype
2107 , nested
2108 , path
2109 , type
2110 , val;
2111
21120 while (i--) {
21130 path = paths[i];
21140 val = obj[path];
2115
21160 if ('$or' === path || '$nor' === path || '$and' === path) {
21170 var k = val.length
2118 , orComponentQuery;
2119
21200 while (k--) {
21210 orComponentQuery = new Query(val[k], {}, null, this.mongooseCollection);
21220 orComponentQuery.cast(model);
21230 val[k] = orComponentQuery._conditions;
2124 }
2125
21260 } else if (path === '$where') {
21270 type = typeof val;
2128
21290 if ('string' !== type && 'function' !== type) {
21300 throw new Error("Must have a string or function for $where");
2131 }
2132
21330 if ('function' === type) {
21340 obj[path] = val.toString();
2135 }
2136
21370 continue;
2138
2139 } else {
2140
21410 if (!schema) {
2142 // no casting for Mixed types
21430 continue;
2144 }
2145
21460 schematype = schema.path(path);
2147
21480 if (!schematype) {
2149 // Handle potential embedded array queries
21500 var split = path.split('.')
2151 , j = split.length
2152 , pathFirstHalf
2153 , pathLastHalf
2154 , remainingConds
2155 , castingQuery;
2156
2157 // Find the part of the var path that is a path of the Schema
21580 while (j--) {
21590 pathFirstHalf = split.slice(0, j).join('.');
21600 schematype = schema.path(pathFirstHalf);
21610 if (schematype) break;
2162 }
2163
2164 // If a substring of the input path resolves to an actual real path...
21650 if (schematype) {
2166 // Apply the casting; similar code for $elemMatch in schema/array.js
21670 if (schematype.caster && schematype.caster.schema) {
21680 remainingConds = {};
21690 pathLastHalf = split.slice(j).join('.');
21700 remainingConds[pathLastHalf] = val;
21710 castingQuery = new Query(remainingConds, {}, null, this.mongooseCollection);
21720 castingQuery.cast(schematype.caster);
21730 obj[path] = castingQuery._conditions[pathLastHalf];
2174 } else {
21750 obj[path] = val;
2176 }
21770 continue;
2178 }
2179
21800 if (utils.isObject(val)) {
2181 // handle geo schemas that use object notation
2182 // { loc: { long: Number, lat: Number }
2183
21840 var geo = val.$near ? '$near' :
2185 val.$nearSphere ? '$nearSphere' :
2186 val.$within ? '$within' :
2187 val.$geoIntersects ? '$geoIntersects' : '';
2188
21890 if (!geo) {
21900 continue;
2191 }
2192
21930 var numbertype = new Types.Number('__QueryCasting__')
21940 var value = val[geo];
2195
21960 if (val.$maxDistance) {
21970 val.$maxDistance = numbertype.castForQuery(val.$maxDistance);
2198 }
2199
22000 if ('$within' == geo) {
22010 var withinType = value.$center
2202 || value.$centerSphere
2203 || value.$box
2204 || value.$polygon;
2205
22060 if (!withinType) {
22070 throw new Error('Bad $within paramater: ' + JSON.stringify(val));
2208 }
2209
22100 value = withinType;
2211
22120 } else if ('$near' == geo &&
2213 'string' == typeof value.type && Array.isArray(value.coordinates)) {
2214 // geojson; cast the coordinates
22150 value = value.coordinates;
2216
22170 } else if (('$near' == geo || '$geoIntersects' == geo) &&
2218 value.$geometry && 'string' == typeof value.$geometry.type &&
2219 Array.isArray(value.$geometry.coordinates)) {
2220 // geojson; cast the coordinates
22210 value = value.$geometry.coordinates;
2222 }
2223
22240 ;(function _cast (val) {
22250 if (Array.isArray(val)) {
22260 val.forEach(function (item, i) {
22270 if (Array.isArray(item) || utils.isObject(item)) {
22280 return _cast(item);
2229 }
22300 val[i] = numbertype.castForQuery(item);
2231 });
2232 } else {
22330 var nearKeys= Object.keys(val);
22340 var nearLen = nearKeys.length;
22350 while (nearLen--) {
22360 var nkey = nearKeys[nearLen];
22370 var item = val[nkey];
22380 if (Array.isArray(item) || utils.isObject(item)) {
22390 _cast(item);
22400 val[nkey] = item;
2241 } else {
22420 val[nkey] = numbertype.castForQuery(item);
2243 }
2244 }
2245 }
2246 })(value);
2247 }
2248
22490 } else if (val === null || val === undefined) {
22500 continue;
22510 } else if ('Object' === val.constructor.name) {
2252
22530 any$conditionals = Object.keys(val).some(function (k) {
22540 return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
2255 });
2256
22570 if (!any$conditionals) {
22580 obj[path] = schematype.castForQuery(val);
2259 } else {
2260
22610 var ks = Object.keys(val)
2262 , k = ks.length
2263 , $cond;
2264
22650 while (k--) {
22660 $cond = ks[k];
22670 nested = val[$cond];
2268
22690 if ('$exists' === $cond) {
22700 if ('boolean' !== typeof nested) {
22710 throw new Error("$exists parameter must be Boolean");
2272 }
22730 continue;
2274 }
2275
22760 if ('$type' === $cond) {
22770 if ('number' !== typeof nested) {
22780 throw new Error("$type parameter must be Number");
2279 }
22800 continue;
2281 }
2282
22830 if ('$not' === $cond) {
22840 this.cast(model, nested);
2285 } else {
22860 val[$cond] = schematype.castForQuery($cond, nested);
2287 }
2288 }
2289 }
2290 } else {
22910 obj[path] = schematype.castForQuery(val);
2292 }
2293 }
2294 }
2295
22960 return obj;
2297}
2298
2299/**
2300 * Casts selected field arguments for field selection with mongo 2.2
2301 *
2302 * query.select({ ids: { $elemMatch: { $in: [hexString] }})
2303 *
2304 * @param {Object} fields
2305 * @see https://github.com/LearnBoost/mongoose/issues/1091
2306 * @see http://docs.mongodb.org/manual/reference/projection/elemMatch/
2307 * @api private
2308 */
2309
23101Query.prototype._castFields = function _castFields (fields) {
23110 var selected
2312 , elemMatchKeys
2313 , keys
2314 , key
2315 , out
2316 , i
2317
23180 if (fields) {
23190 keys = Object.keys(fields);
23200 elemMatchKeys = [];
23210 i = keys.length;
2322
2323 // collect $elemMatch args
23240 while (i--) {
23250 key = keys[i];
23260 if (fields[key].$elemMatch) {
23270 selected || (selected = {});
23280 selected[key] = fields[key];
23290 elemMatchKeys.push(key);
2330 }
2331 }
2332 }
2333
23340 if (selected) {
2335 // they passed $elemMatch, cast em
23360 try {
23370 out = this.cast(this.model, selected);
2338 } catch (err) {
23390 return err;
2340 }
2341
2342 // apply the casted field args
23430 i = elemMatchKeys.length;
23440 while (i--) {
23450 key = elemMatchKeys[i];
23460 fields[key] = out[key];
2347 }
2348 }
2349
23500 return fields;
2351}
2352
2353/**
2354 * Applies schematype selected options to this query.
2355 * @api private
2356 */
2357
23581Query.prototype._applyPaths = function applyPaths () {
2359 // determine if query is selecting or excluding fields
2360
23610 var fields = this._fields
2362 , exclude
2363 , keys
2364 , ki
2365
23660 if (fields) {
23670 keys = Object.keys(fields);
23680 ki = keys.length;
2369
23700 while (ki--) {
23710 if ('+' == keys[ki][0]) continue;
23720 exclude = 0 === fields[keys[ki]];
23730 break;
2374 }
2375 }
2376
2377 // if selecting, apply default schematype select:true fields
2378 // if excluding, apply schematype select:false fields
2379
23800 var selected = []
2381 , excluded = []
2382 , seen = [];
2383
23840 analyzeSchema(this.model.schema);
2385
23860 switch (exclude) {
2387 case true:
23880 excluded.length && this.select('-' + excluded.join(' -'));
23890 break;
2390 case false:
23910 selected.length && this.select(selected.join(' '));
23920 break;
2393 case undefined:
2394 // user didn't specify fields, implies returning all fields.
2395 // only need to apply excluded fields
23960 excluded.length && this.select('-' + excluded.join(' -'));
23970 break;
2398 }
2399
24000 return seen = excluded = selected = keys = fields = null;
2401
24020 function analyzeSchema (schema, prefix) {
24030 prefix || (prefix = '');
2404
2405 // avoid recursion
24060 if (~seen.indexOf(schema)) return;
24070 seen.push(schema);
2408
24090 schema.eachPath(function (path, type) {
24100 if (prefix) path = prefix + '.' + path;
2411
24120 analyzePath(path, type);
2413
2414 // array of subdocs?
24150 if (type.schema) {
24160 analyzeSchema(type.schema, path);
2417 }
2418
2419 });
2420 }
2421
24220 function analyzePath (path, type) {
24230 if ('boolean' != typeof type.selected) return;
2424
24250 var plusPath = '+' + path;
24260 if (fields && plusPath in fields) {
2427 // forced inclusion
24280 delete fields[plusPath];
2429
2430 // if there are other fields being included, add this one
2431 // if no other included fields, leave this out (implied inclusion)
24320 if (false === exclude && keys.length > 1 && !~keys.indexOf(path)) {
24330 fields[path] = 1;
2434 }
2435
24360 return
2437 };
2438
2439 // check for parent exclusions
24400 var root = path.split('.')[0];
24410 if (~excluded.indexOf(root)) return;
2442
24430 ;(type.selected ? selected : excluded).push(path);
2444 }
2445}
2446
2447/**
2448 * Casts selected field arguments for field selection with mongo 2.2
2449 *
2450 * query.select({ ids: { $elemMatch: { $in: [hexString] }})
2451 *
2452 * @param {Object} fields
2453 * @see https://github.com/LearnBoost/mongoose/issues/1091
2454 * @see http://docs.mongodb.org/manual/reference/projection/elemMatch/
2455 * @api private
2456 */
2457
24581Query.prototype._castFields = function _castFields (fields) {
24590 var selected
2460 , elemMatchKeys
2461 , keys
2462 , key
2463 , out
2464 , i
2465
24660 if (fields) {
24670 keys = Object.keys(fields);
24680 elemMatchKeys = [];
24690 i = keys.length;
2470
2471 // collect $elemMatch args
24720 while (i--) {
24730 key = keys[i];
24740 if (fields[key].$elemMatch) {
24750 selected || (selected = {});
24760 selected[key] = fields[key];
24770 elemMatchKeys.push(key);
2478 }
2479 }
2480 }
2481
24820 if (selected) {
2483 // they passed $elemMatch, cast em
24840 try {
24850 out = this.cast(this.model, selected);
2486 } catch (err) {
24870 return err;
2488 }
2489
2490 // apply the casted field args
24910 i = elemMatchKeys.length;
24920 while (i--) {
24930 key = elemMatchKeys[i];
24940 fields[key] = out[key];
2495 }
2496 }
2497
24980 return fields;
2499}
2500
2501/**
2502 * Returns a Node.js 0.8 style [read stream](http://nodejs.org/docs/v0.8.21/api/stream.html#stream_readable_stream) interface.
2503 *
2504 * ####Example
2505 *
2506 * // follows the nodejs 0.8 stream api
2507 * Thing.find({ name: /^hello/ }).stream().pipe(res)
2508 *
2509 * // manual streaming
2510 * var stream = Thing.find({ name: /^hello/ }).stream();
2511 *
2512 * stream.on('data', function (doc) {
2513 * // do something with the mongoose document
2514 * }).on('error', function (err) {
2515 * // handle the error
2516 * }).on('close', function () {
2517 * // the stream is closed
2518 * });
2519 *
2520 * ####Valid options
2521 *
2522 * - `transform`: optional function which accepts a mongoose document. The return value of the function will be emitted on `data`.
2523 *
2524 * ####Example
2525 *
2526 * // JSON.stringify all documents before emitting
2527 * var stream = Thing.find().stream({ transform: JSON.stringify });
2528 * stream.pipe(writeStream);
2529 *
2530 * @return {QueryStream}
2531 * @param {Object} [options]
2532 * @see QueryStream
2533 * @api public
2534 */
2535
25361Query.prototype.stream = function stream (opts) {
25370 return new QueryStream(this, opts);
2538}
2539
2540// the rest of these are basically to support older Mongoose syntax with mquery
2541
2542/**
2543 * _DEPRECATED_ Alias of `maxScan`
2544 *
2545 * @deprecated
2546 * @see maxScan #query_Query-maxScan
2547 * @method maxscan
2548 * @memberOf Query
2549 */
2550
25511Query.prototype.maxscan = Query.base.maxScan;
2552
2553/**
2554 * Sets the tailable option (for use with capped collections).
2555 *
2556 * ####Example
2557 *
2558 * query.tailable() // true
2559 * query.tailable(true)
2560 * query.tailable(false)
2561 *
2562 * ####Note
2563 *
2564 * Cannot be used with `distinct()`
2565 *
2566 * @param {Boolean} bool defaults to true
2567 * @see tailable http://docs.mongodb.org/manual/tutorial/create-tailable-cursor/
2568 * @api public
2569 */
2570
25711Query.prototype.tailable = function (val, opts) {
2572 // we need to support the tailable({ awaitdata : true }) as well as the
2573 // tailable(true, {awaitdata :true}) syntax that mquery does not support
25740 if (val && val.constructor.name == 'Object') {
25750 opts = val;
25760 val = true;
2577 }
2578
25790 if (val === undefined) {
25800 val = true;
2581 }
2582
25830 if (opts && opts.awaitdata) this.options.awaitdata = true;
25840 return Query.base.tailable.call(this, val);
2585}
2586
2587/**
2588 * Declares an intersects query for `geometry()`.
2589 *
2590 * ####Example
2591 *
2592 * query.where('path').intersects().geometry({
2593 * type: 'LineString'
2594 * , coordinates: [[180.0, 11.0], [180, 9.0]]
2595 * })
2596 *
2597 * query.where('path').intersects({
2598 * type: 'LineString'
2599 * , coordinates: [[180.0, 11.0], [180, 9.0]]
2600 * })
2601 *
2602 * ####NOTE:
2603 *
2604 * **MUST** be used after `where()`.
2605 *
2606 * ####NOTE:
2607 *
2608 * In Mongoose 3.7, `intersects` changed from a getter to a function. If you need the old syntax, use [this](https://github.com/ebensing/mongoose-within).
2609 *
2610 * @method intersects
2611 * @memberOf Query
2612 * @param {Object} [arg]
2613 * @return {Query} this
2614 * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/
2615 * @see geoIntersects http://docs.mongodb.org/manual/reference/operator/geoIntersects/
2616 * @api public
2617 */
2618
2619/**
2620 * Specifies a `$geometry` condition
2621 *
2622 * ####Example
2623 *
2624 * var polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]]
2625 * query.where('loc').within().geometry({ type: 'Polygon', coordinates: polyA })
2626 *
2627 * // or
2628 * var polyB = [[ 0, 0 ], [ 1, 1 ]]
2629 * query.where('loc').within().geometry({ type: 'LineString', coordinates: polyB })
2630 *
2631 * // or
2632 * var polyC = [ 0, 0 ]
2633 * query.where('loc').within().geometry({ type: 'Point', coordinates: polyC })
2634 *
2635 * // or
2636 * query.where('loc').intersects().geometry({ type: 'Point', coordinates: polyC })
2637 *
2638 * The argument is assigned to the most recent path passed to `where()`.
2639 *
2640 * ####NOTE:
2641 *
2642 * `geometry()` **must** come after either `intersects()` or `within()`.
2643 *
2644 * The `object` argument must contain `type` and `coordinates` properties.
2645 * - type {String}
2646 * - coordinates {Array}
2647 *
2648 * @method geometry
2649 * @memberOf Query
2650 * @param {Object} object Must contain a `type` property which is a String and a `coordinates` property which is an Array. See the examples.
2651 * @return {Query} this
2652 * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/
2653 * @see http://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry
2654 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
2655 * @api public
2656 */
2657
2658/**
2659 * Specifies a `$near` or `$nearSphere` condition
2660 *
2661 * These operators return documents sorted by distance.
2662 *
2663 * ####Example
2664 *
2665 * query.where('loc').near({ center: [10, 10] });
2666 * query.where('loc').near({ center: [10, 10], maxDistance: 5 });
2667 * query.where('loc').near({ center: [10, 10], maxDistance: 5, spherical: true });
2668 * query.near('loc', { center: [10, 10], maxDistance: 5 });
2669 *
2670 * @method near
2671 * @memberOf Query
2672 * @param {String} [path]
2673 * @param {Object} val
2674 * @return {Query} this
2675 * @see $near http://docs.mongodb.org/manual/reference/operator/near/
2676 * @see $nearSphere http://docs.mongodb.org/manual/reference/operator/nearSphere/
2677 * @see $maxDistance http://docs.mongodb.org/manual/reference/operator/maxDistance/
2678 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
2679 * @api public
2680 */
2681
2682/*!
2683 * Overwriting mquery is needed to support a couple different near() forms found in older
2684 * versions of mongoose
2685 * near([1,1])
2686 * near(1,1)
2687 * near(field, [1,2])
2688 * near(field, 1, 2)
2689 * In addition to all of the normal forms supported by mquery
2690 */
2691
26921Query.prototype.near = function () {
26930 var params = [];
26940 var sphere = this._mongooseOptions.nearSphere;
2695
2696 // TODO refactor
2697
26980 if (arguments.length === 1) {
26990 if (Array.isArray(arguments[0])) {
27000 params.push({ center: arguments[0], spherical: sphere });
27010 } else if ('string' == typeof arguments[0]) {
2702 // just passing a path
27030 params.push(arguments[0]);
27040 } else if (utils.isObject(arguments[0])) {
27050 if ('boolean' != typeof arguments[0].spherical) {
27060 arguments[0].spherical = sphere;
2707 }
27080 params.push(arguments[0]);
2709 } else {
27100 throw new TypeError('invalid argument');
2711 }
27120 } else if (arguments.length === 2) {
27130 if ('number' == typeof arguments[0] && 'number' == typeof arguments[1]) {
27140 params.push({ center: [arguments[0], arguments[1]], spherical: sphere});
27150 } else if ('string' == typeof arguments[0] && Array.isArray(arguments[1])) {
27160 params.push(arguments[0]);
27170 params.push({ center: arguments[1], spherical: sphere });
27180 } else if ('string' == typeof arguments[0] && utils.isObject(arguments[1])) {
27190 params.push(arguments[0]);
27200 if ('boolean' != typeof arguments[1].spherical) {
27210 arguments[1].spherical = sphere;
2722 }
27230 params.push(arguments[1]);
2724 } else {
27250 throw new TypeError('invalid argument');
2726 }
27270 } else if (arguments.length === 3) {
27280 if ('string' == typeof arguments[0] && 'number' == typeof arguments[1]
2729 && 'number' == typeof arguments[2]) {
27300 params.push(arguments[0]);
27310 params.push({ center: [arguments[1], arguments[2]], spherical: sphere });
2732 } else {
27330 throw new TypeError('invalid argument');
2734 }
2735 } else {
27360 throw new TypeError('invalid argument');
2737 }
2738
27390 return Query.base.near.apply(this, params);
2740}
2741
2742/**
2743 * _DEPRECATED_ Specifies a `$nearSphere` condition
2744 *
2745 * ####Example
2746 *
2747 * query.where('loc').nearSphere({ center: [10, 10], maxDistance: 5 });
2748 *
2749 * **Deprecated.** Use `query.near()` instead with the `spherical` option set to `true`.
2750 *
2751 * ####Example
2752 *
2753 * query.where('loc').near({ center: [10, 10], spherical: true });
2754 *
2755 * @deprecated
2756 * @see near() #query_Query-near
2757 * @see $near http://docs.mongodb.org/manual/reference/operator/near/
2758 * @see $nearSphere http://docs.mongodb.org/manual/reference/operator/nearSphere/
2759 * @see $maxDistance http://docs.mongodb.org/manual/reference/operator/maxDistance/
2760 */
2761
27621Query.prototype.nearSphere = function () {
27630 this._mongooseOptions.nearSphere = true;
27640 this.near.apply(this, arguments);
27650 return this;
2766}
2767
2768/**
2769 * Specifies a $polygon condition
2770 *
2771 * ####Example
2772 *
2773 * query.where('loc').within().polygon([10,20], [13, 25], [7,15])
2774 * query.polygon('loc', [10,20], [13, 25], [7,15])
2775 *
2776 * @method polygon
2777 * @memberOf Query
2778 * @param {String|Array} [path]
2779 * @param {Array|Object} [coordinatePairs...]
2780 * @return {Query} this
2781 * @see $polygon http://docs.mongodb.org/manual/reference/operator/polygon/
2782 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
2783 * @api public
2784 */
2785
2786/**
2787 * Specifies a $box condition
2788 *
2789 * ####Example
2790 *
2791 * var lowerLeft = [40.73083, -73.99756]
2792 * var upperRight= [40.741404, -73.988135]
2793 *
2794 * query.where('loc').within().box(lowerLeft, upperRight)
2795 * query.box({ ll : lowerLeft, ur : upperRight })
2796 *
2797 * @method box
2798 * @memberOf Query
2799 * @see $box http://docs.mongodb.org/manual/reference/operator/box/
2800 * @see within() Query#within #query_Query-within
2801 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
2802 * @param {Object} val
2803 * @param [Array] Upper Right Coords
2804 * @return {Query} this
2805 * @api public
2806 */
2807
2808/*!
2809 * this is needed to support the mongoose syntax of:
2810 * box(field, { ll : [x,y], ur : [x2,y2] })
2811 * box({ ll : [x,y], ur : [x2,y2] })
2812 */
2813
28141Query.prototype.box = function (ll, ur) {
28150 if (!Array.isArray(ll) && utils.isObject(ll)) {
28160 ur = ll.ur;
28170 ll = ll.ll;
2818 }
28190 return Query.base.box.call(this, ll, ur);
2820}
2821
2822/**
2823 * Specifies a $center or $centerSphere condition.
2824 *
2825 * ####Example
2826 *
2827 * var area = { center: [50, 50], radius: 10, unique: true }
2828 * query.where('loc').within().circle(area)
2829 * // alternatively
2830 * query.circle('loc', area);
2831 *
2832 * // spherical calculations
2833 * var area = { center: [50, 50], radius: 10, unique: true, spherical: true }
2834 * query.where('loc').within().circle(area)
2835 * // alternatively
2836 * query.circle('loc', area);
2837 *
2838 * New in 3.7.0
2839 *
2840 * @method circle
2841 * @memberOf Query
2842 * @param {String} [path]
2843 * @param {Object} area
2844 * @return {Query} this
2845 * @see $center http://docs.mongodb.org/manual/reference/operator/center/
2846 * @see $centerSphere http://docs.mongodb.org/manual/reference/operator/centerSphere/
2847 * @see $geoWithin http://docs.mongodb.org/manual/reference/operator/within/
2848 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
2849 * @api public
2850 */
2851
2852/**
2853 * _DEPRECATED_ Alias for [circle](#query_Query-circle)
2854 *
2855 * **Deprecated.** Use [circle](#query_Query-circle) instead.
2856 *
2857 * @deprecated
2858 * @method center
2859 * @memberOf Query
2860 * @api public
2861 */
2862
28631Query.prototype.center = Query.base.circle;
2864
2865/**
2866 * _DEPRECATED_ Specifies a $centerSphere condition
2867 *
2868 * **Deprecated.** Use [circle](#query_Query-circle) instead.
2869 *
2870 * ####Example
2871 *
2872 * var area = { center: [50, 50], radius: 10 };
2873 * query.where('loc').within().centerSphere(area);
2874 *
2875 * @deprecated
2876 * @param {String} [path]
2877 * @param {Object} val
2878 * @return {Query} this
2879 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
2880 * @see $centerSphere http://docs.mongodb.org/manual/reference/operator/centerSphere/
2881 * @api public
2882 */
2883
28841Query.prototype.centerSphere = function () {
28850 if (arguments[0] && arguments[0].constructor.name == 'Object') {
28860 arguments[0].spherical = true;
2887 }
2888
28890 if (arguments[1] && arguments[1].constructor.name == 'Object') {
28900 arguments[1].spherical = true;
2891 }
2892
28930 Query.base.circle.apply(this, arguments);
2894}
2895
2896/**
2897 * Determines if query fields are inclusive
2898 *
2899 * @return {Boolean} bool defaults to true
2900 * @api private
2901 */
2902
29031Query.prototype._selectedInclusively = Query.prototype.selectedInclusively;
2904
2905/*!
2906 * Remove from public api for 3.8
2907 */
2908
29091Query.prototype.selected =
2910Query.prototype.selectedInclusively =
2911Query.prototype.selectedExclusively = undefined;
2912
2913/*!
2914 * Export
2915 */
2916
29171module.exports = Query;
2918

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/queryhelpers.js

27%
18
5
13
LineHitsSource
1
2/*!
3 * Module dependencies
4 */
5
61var utils = require('./utils')
7
8/*!
9 * Prepare a set of path options for query population.
10 *
11 * @param {Query} query
12 * @param {Object} options
13 * @return {Array}
14 */
15
161exports.preparePopulationOptions = function preparePopulationOptions (query, options) {
170 var pop = utils.object.vals(query.options.populate);
18
19 // lean options should trickle through all queries
200 if (options.lean) pop.forEach(makeLean);
21
220 return pop;
23}
24
25/*!
26 * Prepare a set of path options for query population. This is the MongooseQuery
27 * version
28 *
29 * @param {Query} query
30 * @param {Object} options
31 * @return {Array}
32 */
33
341exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ (query, options) {
350 var pop = utils.object.vals(query._mongooseOptions.populate);
36
37 // lean options should trickle through all queries
380 if (options.lean) pop.forEach(makeLean);
39
400 return pop;
41}
42
43/*!
44 * If the document is a mapped discriminator type, it returns a model instance for that type, otherwise,
45 * it returns an instance of the given model.
46 *
47 * @param {Model} model
48 * @param {Object} doc
49 * @param {Object} fields
50 *
51 * @return {Model}
52 */
531exports.createModel = function createModel(model, doc, fields) {
540 var discriminatorMapping = model.schema
55 ? model.schema.discriminatorMapping
56 : null;
57
580 var key = discriminatorMapping && discriminatorMapping.isRoot
59 ? discriminatorMapping.key
60 : null;
61
620 if (key && doc[key] && model.discriminators && model.discriminators[doc[key]]) {
630 return new model.discriminators[doc[key]](undefined, fields, true);
64 }
65
660 return new model(undefined, fields, true);
67}
68
69/*!
70 * Set each path query option to lean
71 *
72 * @param {Object} option
73 */
74
751function makeLean (option) {
760 option.options || (option.options = {});
770 option.options.lean = true;
78}
79
80

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/querystream.js

20%
105
21
84
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var Stream = require('stream').Stream
71var utils = require('./utils')
81var helpers = require('./queryhelpers')
91var K = function(k){ return k }
10
11/**
12 * Provides a Node.js 0.8 style [ReadStream](http://nodejs.org/docs/v0.8.21/api/stream.html#stream_readable_stream) interface for Queries.
13 *
14 * var stream = Model.find().stream();
15 *
16 * stream.on('data', function (doc) {
17 * // do something with the mongoose document
18 * }).on('error', function (err) {
19 * // handle the error
20 * }).on('close', function () {
21 * // the stream is closed
22 * });
23 *
24 *
25 * The stream interface allows us to simply "plug-in" to other _Node.js 0.8_ style write streams.
26 *
27 * Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);
28 *
29 * ####Valid options
30 *
31 * - `transform`: optional function which accepts a mongoose document. The return value of the function will be emitted on `data`.
32 *
33 * ####Example
34 *
35 * // JSON.stringify all documents before emitting
36 * var stream = Thing.find().stream({ transform: JSON.stringify });
37 * stream.pipe(writeStream);
38 *
39 * _NOTE: plugging into an HTTP response will *not* work out of the box. Those streams expect only strings or buffers to be emitted, so first formatting our documents as strings/buffers is necessary._
40 *
41 * _NOTE: these streams are Node.js 0.8 style read streams which differ from Node.js 0.10 style. Node.js 0.10 streams are not well tested yet and are not guaranteed to work._
42 *
43 * @param {Query} query
44 * @param {Object} [options]
45 * @inherits NodeJS Stream http://nodejs.org/docs/v0.8.21/api/stream.html#stream_readable_stream
46 * @event `data`: emits a single Mongoose document
47 * @event `error`: emits when an error occurs during streaming. This will emit _before_ the `close` event.
48 * @event `close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted.
49 * @api public
50 */
51
521function QueryStream (query, options) {
530 Stream.call(this);
54
550 this.query = query;
560 this.readable = true;
570 this.paused = false;
580 this._cursor = null;
590 this._destroyed = null;
600 this._fields = null;
610 this._buffer = null;
620 this._inline = T_INIT;
630 this._running = false;
640 this._transform = options && 'function' == typeof options.transform
65 ? options.transform
66 : K;
67
68 // give time to hook up events
690 var self = this;
700 process.nextTick(function () {
710 self._init();
72 });
73}
74
75/*!
76 * Inherit from Stream
77 */
78
791QueryStream.prototype.__proto__ = Stream.prototype;
80
81/**
82 * Flag stating whether or not this stream is readable.
83 *
84 * @property readable
85 * @api public
86 */
87
881QueryStream.prototype.readable;
89
90/**
91 * Flag stating whether or not this stream is paused.
92 *
93 * @property paused
94 * @api public
95 */
96
971QueryStream.prototype.paused;
98
99// trampoline flags
1001var T_INIT = 0;
1011var T_IDLE = 1;
1021var T_CONT = 2;
103
104/**
105 * Initializes the query.
106 *
107 * @api private
108 */
109
1101QueryStream.prototype._init = function () {
1110 if (this._destroyed) return;
112
1130 var query = this.query
114 , model = query.model
115 , options = query._optionsForExec(model)
116 , self = this
117
1180 try {
1190 query.cast(model);
120 } catch (err) {
1210 return self.destroy(err);
122 }
123
1240 self._fields = utils.clone(query._fields);
1250 options.fields = query._castFields(self._fields);
126
1270 model.collection.find(query._conditions, options, function (err, cursor) {
1280 if (err) return self.destroy(err);
1290 self._cursor = cursor;
1300 self._next();
131 });
132}
133
134/**
135 * Trampoline for pulling the next doc from cursor.
136 *
137 * @see QueryStream#__next #querystream_QueryStream-__next
138 * @api private
139 */
140
1411QueryStream.prototype._next = function _next () {
1420 if (this.paused || this._destroyed) {
1430 return this._running = false;
144 }
145
1460 this._running = true;
147
1480 if (this._buffer && this._buffer.length) {
1490 var arg;
1500 while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
1510 this._onNextObject.apply(this, arg);
152 }
153 }
154
155 // avoid stack overflows with large result sets.
156 // trampoline instead of recursion.
1570 while (this.__next()) {}
158}
159
160/**
161 * Pulls the next doc from the cursor.
162 *
163 * @see QueryStream#_next #querystream_QueryStream-_next
164 * @api private
165 */
166
1671QueryStream.prototype.__next = function () {
1680 if (this.paused || this._destroyed)
1690 return this._running = false;
170
1710 var self = this;
1720 self._inline = T_INIT;
173
1740 self._cursor.nextObject(function cursorcb (err, doc) {
1750 self._onNextObject(err, doc);
176 });
177
178 // if onNextObject() was already called in this tick
179 // return ourselves to the trampoline.
1800 if (T_CONT === this._inline) {
1810 return true;
182 } else {
183 // onNextObject() hasn't fired yet. tell onNextObject
184 // that its ok to call _next b/c we are not within
185 // the trampoline anymore.
1860 this._inline = T_IDLE;
187 }
188}
189
190/**
191 * Transforms raw `doc`s returned from the cursor into a model instance.
192 *
193 * @param {Error|null} err
194 * @param {Object} doc
195 * @api private
196 */
197
1981QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
1990 if (this._destroyed) return;
200
2010 if (this.paused) {
2020 this._buffer || (this._buffer = []);
2030 this._buffer.push([err, doc]);
2040 return this._running = false;
205 }
206
2070 if (err) return this.destroy(err);
208
209 // when doc is null we hit the end of the cursor
2100 if (!doc) {
2110 this.emit('end');
2120 return this.destroy();
213 }
214
2150 var opts = this.query._mongooseOptions;
216
2170 if (!opts.populate) {
2180 return true === opts.lean
219 ? emit(this, doc)
220 : createAndEmit(this, doc);
221 }
222
2230 var self = this;
2240 var pop = helpers.preparePopulationOptionsMQ(self.query, self.query._mongooseOptions);
225
2260 self.query.model.populate(doc, pop, function (err, doc) {
2270 if (err) return self.destroy(err);
2280 return true === opts.lean
229 ? emit(self, doc)
230 : createAndEmit(self, doc);
231 })
232}
233
2341function createAndEmit (self, doc) {
2350 var instance = helpers.createModel(self.query.model, doc, self._fields);
236
2370 instance.init(doc, function (err) {
2380 if (err) return self.destroy(err);
2390 emit(self, instance);
240 });
241}
242
243/*!
244 * Emit a data event and manage the trampoline state
245 */
246
2471function emit (self, doc) {
2480 self.emit('data', self._transform(doc));
249
250 // trampoline management
2510 if (T_IDLE === self._inline) {
252 // no longer in trampoline. restart it.
2530 self._next();
254 } else {
255 // in a trampoline. tell __next that its
256 // ok to continue jumping.
2570 self._inline = T_CONT;
258 }
259}
260
261/**
262 * Pauses this stream.
263 *
264 * @api public
265 */
266
2671QueryStream.prototype.pause = function () {
2680 this.paused = true;
269}
270
271/**
272 * Resumes this stream.
273 *
274 * @api public
275 */
276
2771QueryStream.prototype.resume = function () {
2780 this.paused = false;
279
2800 if (!this._cursor) {
281 // cannot start if not initialized
2820 return;
283 }
284
285 // are we within the trampoline?
2860 if (T_INIT === this._inline) {
2870 return;
288 }
289
2900 if (!this._running) {
291 // outside QueryStream control, need manual restart
2920 return this._next();
293 }
294}
295
296/**
297 * Destroys the stream, closing the underlying cursor. No more events will be emitted.
298 *
299 * @param {Error} [err]
300 * @api public
301 */
302
3031QueryStream.prototype.destroy = function (err) {
3040 if (this._destroyed) return;
3050 this._destroyed = true;
3060 this._running = false;
3070 this.readable = false;
308
3090 if (this._cursor) {
3100 this._cursor.close();
311 }
312
3130 if (err) {
3140 this.emit('error', err);
315 }
316
3170 this.emit('close');
318}
319
320/**
321 * Pipes this query stream into another stream. This method is inherited from NodeJS Streams.
322 *
323 * ####Example:
324 *
325 * query.stream().pipe(writeStream [, options])
326 *
327 * @method pipe
328 * @memberOf QueryStream
329 * @see NodeJS http://nodejs.org/api/stream.html
330 * @api public
331 */
332
333/*!
334 * Module exports
335 */
336
3371module.exports = exports = QueryStream;
338

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema.js

36%
241
87
154
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var EventEmitter = require('events').EventEmitter
6 , VirtualType = require('./virtualtype')
7 , utils = require('./utils')
8 , mquery = require('mquery')
9 , Query
10 , Types
11
12/**
13 * Schema constructor.
14 *
15 * ####Example:
16 *
17 * var child = new Schema({ name: String });
18 * var schema = new Schema({ name: String, age: Number, children: [child] });
19 * var Tree = mongoose.model('Tree', schema);
20 *
21 * // setting schema options
22 * new Schema({ name: String }, { _id: false, autoIndex: false })
23 *
24 * ####Options:
25 *
26 * - [autoIndex](/docs/guide.html#autoIndex): bool - defaults to true
27 * - [bufferCommands](/docs/guide.html#bufferCommands): bool - defaults to true
28 * - [capped](/docs/guide.html#capped): bool - defaults to false
29 * - [collection](/docs/guide.html#collection): string - no default
30 * - [id](/docs/guide.html#id): bool - defaults to true
31 * - [_id](/docs/guide.html#_id): bool - defaults to true
32 * - `minimize`: bool - controls [document#toObject](#document_Document-toObject) behavior when called manually - defaults to true
33 * - [read](/docs/guide.html#read): string
34 * - [safe](/docs/guide.html#safe): bool - defaults to true.
35 * - [shardKey](/docs/guide.html#shardKey): bool - defaults to `null`
36 * - [strict](/docs/guide.html#strict): bool - defaults to true
37 * - [toJSON](/docs/guide.html#toJSON) - object - no default
38 * - [toObject](/docs/guide.html#toObject) - object - no default
39 * - [versionKey](/docs/guide.html#versionKey): bool - defaults to "__v"
40 *
41 * ####Note:
42 *
43 * _When nesting schemas, (`children` in the example above), always declare the child schema first before passing it into is parent._
44 *
45 * @param {Object} definition
46 * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
47 * @event `init`: Emitted after the schema is compiled into a `Model`.
48 * @api public
49 */
50
511function Schema (obj, options) {
521 if (!(this instanceof Schema))
530 return new Schema(obj, options);
54
551 this.paths = {};
561 this.subpaths = {};
571 this.virtuals = {};
581 this.nested = {};
591 this.inherits = {};
601 this.callQueue = [];
611 this._indexes = [];
621 this.methods = {};
631 this.statics = {};
641 this.tree = {};
651 this._requiredpaths = undefined;
661 this.discriminatorMapping = undefined;
671 this._indexedpaths = undefined;
68
691 this.options = this.defaultOptions(options);
70
71 // build paths
721 if (obj) {
731 this.add(obj);
74 }
75
76 // ensure the documents get an auto _id unless disabled
771 var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
781 if (auto_id) {
790 this.add({ _id: {type: Schema.ObjectId, auto: true} });
80 }
81
82 // ensure the documents receive an id getter unless disabled
831 var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
841 if (autoid) {
850 this.virtual('id').get(idGetter);
86 }
87}
88
89/*!
90 * Returns this documents _id cast to a string.
91 */
92
931function idGetter () {
940 if (this.$__._id) {
950 return this.$__._id;
96 }
97
980 return this.$__._id = null == this._id
99 ? null
100 : String(this._id);
101}
102
103/*!
104 * Inherit from EventEmitter.
105 */
106
1071Schema.prototype.__proto__ = EventEmitter.prototype;
108
109/**
110 * Schema as flat paths
111 *
112 * ####Example:
113 * {
114 * '_id' : SchemaType,
115 * , 'nested.key' : SchemaType,
116 * }
117 *
118 * @api private
119 * @property paths
120 */
121
1221Schema.prototype.paths;
123
124/**
125 * Schema as a tree
126 *
127 * ####Example:
128 * {
129 * '_id' : ObjectId
130 * , 'nested' : {
131 * 'key' : String
132 * }
133 * }
134 *
135 * @api private
136 * @property tree
137 */
138
1391Schema.prototype.tree;
140
141/**
142 * Returns default options for this schema, merged with `options`.
143 *
144 * @param {Object} options
145 * @return {Object}
146 * @api private
147 */
148
1491Schema.prototype.defaultOptions = function (options) {
1501 if (options && false === options.safe) {
1510 options.safe = { w: 0 };
152 }
153
1541 if (options && options.safe && 0 === options.safe.w) {
155 // if you turn off safe writes, then versioning goes off as well
1560 options.versionKey = false;
157 }
158
1591 options = utils.options({
160 strict: true
161 , bufferCommands: true
162 , capped: false // { size, max, autoIndexId }
163 , versionKey: '__v'
164 , discriminatorKey: '__t'
165 , minimize: true
166 , autoIndex: true
167 , shardKey: null
168 , read: null
169 // the following are only applied at construction time
170 , noId: false // deprecated, use { _id: false }
171 , _id: true
172 , noVirtualId: false // deprecated, use { id: false }
173 , id: true
174// , pluralization: true // only set this to override the global option
175 }, options);
176
1771 if (options.read) {
1780 options.read = utils.readPref(options.read);
179 }
180
1811 return options;
182}
183
184/**
185 * Adds key path / schema type pairs to this schema.
186 *
187 * ####Example:
188 *
189 * var ToySchema = new Schema;
190 * ToySchema.add({ name: 'string', color: 'string', price: 'number' });
191 *
192 * @param {Object} obj
193 * @param {String} prefix
194 * @api public
195 */
196
1971Schema.prototype.add = function add (obj, prefix) {
1981 prefix = prefix || '';
1991 var keys = Object.keys(obj);
200
2011 for (var i = 0; i < keys.length; ++i) {
20217 var key = keys[i];
203
20417 if (null == obj[key]) {
2050 throw new TypeError('Invalid value for schema path `'+ prefix + key +'`');
206 }
207
20817 if (utils.isObject(obj[key]) && (!obj[key].constructor || 'Object' == obj[key].constructor.name) && (!obj[key].type || obj[key].type.type)) {
2090 if (Object.keys(obj[key]).length) {
210 // nested object { last: { name: String }}
2110 this.nested[prefix + key] = true;
2120 this.add(obj[key], prefix + key + '.');
213 } else {
2140 this.path(prefix + key, obj[key]); // mixed type
215 }
216 } else {
21717 this.path(prefix + key, obj[key]);
218 }
219 }
220};
221
222/**
223 * Reserved document keys.
224 *
225 * Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.
226 *
227 * on, emit, _events, db, get, set, init, isNew, errors, schema, options, modelName, collection, _pres, _posts, toObject
228 *
229 * _NOTE:_ Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.
230 *
231 * var schema = new Schema(..);
232 * schema.methods.init = function () {} // potentially breaking
233 */
234
2351Schema.reserved = Object.create(null);
2361var reserved = Schema.reserved;
2371reserved.on =
238reserved.db =
239reserved.set =
240reserved.get =
241reserved.init =
242reserved.isNew =
243reserved.errors =
244reserved.schema =
245reserved.options =
246reserved.modelName =
247reserved.collection =
248reserved.toObject =
249reserved.emit = // EventEmitter
250reserved._events = // EventEmitter
251reserved._pres = reserved._posts = 1 // hooks.js
252
253/**
254 * Gets/sets schema paths.
255 *
256 * Sets a path (if arity 2)
257 * Gets a path (if arity 1)
258 *
259 * ####Example
260 *
261 * schema.path('name') // returns a SchemaType
262 * schema.path('name', Number) // changes the schemaType of `name` to Number
263 *
264 * @param {String} path
265 * @param {Object} constructor
266 * @api public
267 */
268
2691Schema.prototype.path = function (path, obj) {
27017 if (obj == undefined) {
2710 if (this.paths[path]) return this.paths[path];
2720 if (this.subpaths[path]) return this.subpaths[path];
273
274 // subpaths?
2750 return /\.\d+\.?.*$/.test(path)
276 ? getPositionalPath(this, path)
277 : undefined;
278 }
279
280 // some path names conflict with document methods
28117 if (reserved[path]) {
2820 throw new Error("`" + path + "` may not be used as a schema pathname");
283 }
284
285 // update the tree
28617 var subpaths = path.split(/\./)
287 , last = subpaths.pop()
288 , branch = this.tree;
289
29017 subpaths.forEach(function(sub, i) {
2910 if (!branch[sub]) branch[sub] = {};
2920 if ('object' != typeof branch[sub]) {
2930 var msg = 'Cannot set nested path `' + path + '`. '
294 + 'Parent path `'
295 + subpaths.slice(0, i).concat([sub]).join('.')
296 + '` already set to type ' + branch[sub].name
297 + '.';
2980 throw new Error(msg);
299 }
3000 branch = branch[sub];
301 });
302
30317 branch[last] = utils.clone(obj);
304
30517 this.paths[path] = Schema.interpretAsType(path, obj);
30617 return this;
307};
308
309/**
310 * Converts type arguments into Mongoose Types.
311 *
312 * @param {String} path
313 * @param {Object} obj constructor
314 * @api private
315 */
316
3171Schema.interpretAsType = function (path, obj) {
31817 if (obj.constructor && obj.constructor.name != 'Object')
31917 obj = { type: obj };
320
321 // Get the type making sure to allow keys named "type"
322 // and default to mixed if not specified.
323 // { type: { type: String, default: 'freshcut' } }
32417 var type = obj.type && !obj.type.type
325 ? obj.type
326 : {};
327
32817 if ('Object' == type.constructor.name || 'mixed' == type) {
3290 return new Types.Mixed(path, obj);
330 }
331
33217 if (Array.isArray(type) || Array == type || 'array' == type) {
333 // if it was specified through { type } look for `cast`
3340 var cast = (Array == type || 'array' == type)
335 ? obj.cast
336 : type[0];
337
3380 if (cast instanceof Schema) {
3390 return new Types.DocumentArray(path, cast, obj);
340 }
341
3420 if ('string' == typeof cast) {
3430 cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
3440 } else if (cast && (!cast.type || cast.type.type)
345 && 'Object' == cast.constructor.name
346 && Object.keys(cast).length) {
3470 return new Types.DocumentArray(path, new Schema(cast), obj);
348 }
349
3500 return new Types.Array(path, cast || Types.Mixed, obj);
351 }
352
35317 var name = 'string' == typeof type
354 ? type
355 : type.name;
356
35717 if (name) {
35817 name = name.charAt(0).toUpperCase() + name.substring(1);
359 }
360
36117 if (undefined == Types[name]) {
3620 throw new TypeError('Undefined type at `' + path +
363 '`\n Did you try nesting Schemas? ' +
364 'You can only nest using refs or arrays.');
365 }
366
36717 return new Types[name](path, obj);
368};
369
370/**
371 * Iterates the schemas paths similar to Array#forEach.
372 *
373 * The callback is passed the pathname and schemaType as arguments on each iteration.
374 *
375 * @param {Function} fn callback function
376 * @return {Schema} this
377 * @api public
378 */
379
3801Schema.prototype.eachPath = function (fn) {
3810 var keys = Object.keys(this.paths)
382 , len = keys.length;
383
3840 for (var i = 0; i < len; ++i) {
3850 fn(keys[i], this.paths[keys[i]]);
386 }
387
3880 return this;
389};
390
391/**
392 * Returns an Array of path strings that are required by this schema.
393 *
394 * @api public
395 * @return {Array}
396 */
397
3981Schema.prototype.requiredPaths = function requiredPaths () {
3990 if (this._requiredpaths) return this._requiredpaths;
400
4010 var paths = Object.keys(this.paths)
402 , i = paths.length
403 , ret = [];
404
4050 while (i--) {
4060 var path = paths[i];
4070 if (this.paths[path].isRequired) ret.push(path);
408 }
409
4100 return this._requiredpaths = ret;
411}
412
413/**
414 * Returns indexes from fields and schema-level indexes (cached).
415 *
416 * @api private
417 * @return {Array}
418 */
419
4201Schema.prototype.indexedPaths = function indexedPaths () {
4210 if (this._indexedpaths) return this._indexedpaths;
422
4230 return this._indexedpaths = this.indexes();
424}
425
426/**
427 * Returns the pathType of `path` for this schema.
428 *
429 * Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.
430 *
431 * @param {String} path
432 * @return {String}
433 * @api public
434 */
435
4361Schema.prototype.pathType = function (path) {
4370 if (path in this.paths) return 'real';
4380 if (path in this.virtuals) return 'virtual';
4390 if (path in this.nested) return 'nested';
4400 if (path in this.subpaths) return 'real';
441
4420 if (/\.\d+\.|\.\d+$/.test(path) && getPositionalPath(this, path)) {
4430 return 'real';
444 } else {
4450 return 'adhocOrUndefined'
446 }
447};
448
449/*!
450 * ignore
451 */
452
4531function getPositionalPath (self, path) {
4540 var subpaths = path.split(/\.(\d+)\.|\.(\d+)$/).filter(Boolean);
4550 if (subpaths.length < 2) {
4560 return self.paths[subpaths[0]];
457 }
458
4590 var val = self.path(subpaths[0]);
4600 if (!val) return val;
461
4620 var last = subpaths.length - 1
463 , subpath
464 , i = 1;
465
4660 for (; i < subpaths.length; ++i) {
4670 subpath = subpaths[i];
468
4690 if (i === last && val && !val.schema && !/\D/.test(subpath)) {
4700 if (val instanceof Types.Array) {
471 // StringSchema, NumberSchema, etc
4720 val = val.caster;
473 } else {
4740 val = undefined;
475 }
4760 break;
477 }
478
479 // ignore if its just a position segment: path.0.subpath
4800 if (!/\D/.test(subpath)) continue;
481
4820 if (!(val && val.schema)) {
4830 val = undefined;
4840 break;
485 }
486
4870 val = val.schema.path(subpath);
488 }
489
4900 return self.subpaths[path] = val;
491}
492
493/**
494 * Adds a method call to the queue.
495 *
496 * @param {String} name name of the document method to call later
497 * @param {Array} args arguments to pass to the method
498 * @api private
499 */
500
5011Schema.prototype.queue = function(name, args){
5020 this.callQueue.push([name, args]);
5030 return this;
504};
505
506/**
507 * Defines a pre hook for the document.
508 *
509 * ####Example
510 *
511 * var toySchema = new Schema(..);
512 *
513 * toySchema.pre('save', function (next) {
514 * if (!this.created) this.created = new Date;
515 * next();
516 * })
517 *
518 * toySchema.pre('validate', function (next) {
519 * if (this.name != 'Woody') this.name = 'Woody';
520 * next();
521 * })
522 *
523 * @param {String} method
524 * @param {Function} callback
525 * @see hooks.js https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3
526 * @api public
527 */
528
5291Schema.prototype.pre = function(){
5300 return this.queue('pre', arguments);
531};
532
533/**
534 * Defines a post hook for the document
535 *
536 * Post hooks fire `on` the event emitted from document instances of Models compiled from this schema.
537 *
538 * var schema = new Schema(..);
539 * schema.post('save', function (doc) {
540 * console.log('this fired after a document was saved');
541 * });
542 *
543 * var Model = mongoose.model('Model', schema);
544 *
545 * var m = new Model(..);
546 * m.save(function (err) {
547 * console.log('this fires after the `post` hook');
548 * });
549 *
550 * @param {String} method name of the method to hook
551 * @param {Function} fn callback
552 * @see hooks.js https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3
553 * @api public
554 */
555
5561Schema.prototype.post = function(method, fn){
5570 return this.queue('on', arguments);
558};
559
560/**
561 * Registers a plugin for this schema.
562 *
563 * @param {Function} plugin callback
564 * @param {Object} opts
565 * @see plugins
566 * @api public
567 */
568
5691Schema.prototype.plugin = function (fn, opts) {
5700 fn(this, opts);
5710 return this;
572};
573
574/**
575 * Adds an instance method to documents constructed from Models compiled from this schema.
576 *
577 * ####Example
578 *
579 * var schema = kittySchema = new Schema(..);
580 *
581 * schema.method('meow', function () {
582 * console.log('meeeeeoooooooooooow');
583 * })
584 *
585 * var Kitty = mongoose.model('Kitty', schema);
586 *
587 * var fizz = new Kitty;
588 * fizz.meow(); // meeeeeooooooooooooow
589 *
590 * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.
591 *
592 * schema.method({
593 * purr: function () {}
594 * , scratch: function () {}
595 * });
596 *
597 * // later
598 * fizz.purr();
599 * fizz.scratch();
600 *
601 * @param {String|Object} method name
602 * @param {Function} [fn]
603 * @api public
604 */
605
6061Schema.prototype.method = function (name, fn) {
6070 if ('string' != typeof name)
6080 for (var i in name)
6090 this.methods[i] = name[i];
610 else
6110 this.methods[name] = fn;
6120 return this;
613};
614
615/**
616 * Adds static "class" methods to Models compiled from this schema.
617 *
618 * ####Example
619 *
620 * var schema = new Schema(..);
621 * schema.static('findByName', function (name, callback) {
622 * return this.find({ name: name }, callback);
623 * });
624 *
625 * var Drink = mongoose.model('Drink', schema);
626 * Drink.findByName('sanpellegrino', function (err, drinks) {
627 * //
628 * });
629 *
630 * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.
631 *
632 * @param {String} name
633 * @param {Function} fn
634 * @api public
635 */
636
6371Schema.prototype.static = function(name, fn) {
6380 if ('string' != typeof name)
6390 for (var i in name)
6400 this.statics[i] = name[i];
641 else
6420 this.statics[name] = fn;
6430 return this;
644};
645
646/**
647 * Defines an index (most likely compound) for this schema.
648 *
649 * ####Example
650 *
651 * schema.index({ first: 1, last: -1 })
652 *
653 * @param {Object} fields
654 * @param {Object} [options]
655 * @api public
656 */
657
6581Schema.prototype.index = function (fields, options) {
6590 options || (options = {});
660
6610 if (options.expires)
6620 utils.expires(options);
663
6640 this._indexes.push([fields, options]);
6650 return this;
666};
667
668/**
669 * Sets/gets a schema option.
670 *
671 * @param {String} key option name
672 * @param {Object} [value] if not passed, the current option value is returned
673 * @api public
674 */
675
6761Schema.prototype.set = function (key, value, _tags) {
6770 if (1 === arguments.length) {
6780 return this.options[key];
679 }
680
6810 switch (key) {
682 case 'read':
6830 this.options[key] = utils.readPref(value, _tags)
6840 break;
685 case 'safe':
6860 this.options[key] = false === value
687 ? { w: 0 }
688 : value
6890 break;
690 default:
6910 this.options[key] = value;
692 }
693
6940 return this;
695}
696
697/**
698 * Gets a schema option.
699 *
700 * @param {String} key option name
701 * @api public
702 */
703
7041Schema.prototype.get = function (key) {
7050 return this.options[key];
706}
707
708/**
709 * The allowed index types
710 *
711 * @static indexTypes
712 * @receiver Schema
713 * @api public
714 */
715
7161var indexTypes = '2d 2dsphere hashed text'.split(' ');
717
7181Object.defineProperty(Schema, 'indexTypes', {
7190 get: function () { return indexTypes }
7200 , set: function () { throw new Error('Cannot overwrite Schema.indexTypes') }
721})
722
723/**
724 * Compiles indexes from fields and schema-level indexes
725 *
726 * @api public
727 */
728
7291Schema.prototype.indexes = function () {
7300 'use strict';
731
7320 var indexes = []
733 , seenSchemas = []
7340 collectIndexes(this);
7350 return indexes;
736
7370 function collectIndexes (schema, prefix) {
7380 if (~seenSchemas.indexOf(schema)) return;
7390 seenSchemas.push(schema);
740
7410 prefix = prefix || '';
742
7430 var key, path, index, field, isObject, options, type;
7440 var keys = Object.keys(schema.paths);
745
7460 for (var i = 0; i < keys.length; ++i) {
7470 key = keys[i];
7480 path = schema.paths[key];
749
7500 if (path instanceof Types.DocumentArray) {
7510 collectIndexes(path.schema, key + '.');
752 } else {
7530 index = path._index;
754
7550 if (false !== index && null != index) {
7560 field = {};
7570 isObject = utils.isObject(index);
7580 options = isObject ? index : {};
7590 type = 'string' == typeof index ? index :
760 isObject ? index.type :
761 false;
762
7630 if (type && ~Schema.indexTypes.indexOf(type)) {
7640 field[prefix + key] = type;
765 } else {
7660 field[prefix + key] = 1;
767 }
768
7690 delete options.type;
7700 if (!('background' in options)) {
7710 options.background = true;
772 }
773
7740 indexes.push([field, options]);
775 }
776 }
777 }
778
7790 if (prefix) {
7800 fixSubIndexPaths(schema, prefix);
781 } else {
7820 schema._indexes.forEach(function (index) {
7830 if (!('background' in index[1])) index[1].background = true;
784 });
7850 indexes = indexes.concat(schema._indexes);
786 }
787 }
788
789 /*!
790 * Checks for indexes added to subdocs using Schema.index().
791 * These indexes need their paths prefixed properly.
792 *
793 * schema._indexes = [ [indexObj, options], [indexObj, options] ..]
794 */
795
7960 function fixSubIndexPaths (schema, prefix) {
7970 var subindexes = schema._indexes
798 , len = subindexes.length
799 , indexObj
800 , newindex
801 , klen
802 , keys
803 , key
804 , i = 0
805 , j
806
8070 for (i = 0; i < len; ++i) {
8080 indexObj = subindexes[i][0];
8090 keys = Object.keys(indexObj);
8100 klen = keys.length;
8110 newindex = {};
812
813 // use forward iteration, order matters
8140 for (j = 0; j < klen; ++j) {
8150 key = keys[j];
8160 newindex[prefix + key] = indexObj[key];
817 }
818
8190 indexes.push([newindex, subindexes[i][1]]);
820 }
821 }
822}
823
824/**
825 * Creates a virtual type with the given name.
826 *
827 * @param {String} name
828 * @param {Object} [options]
829 * @return {VirtualType}
830 */
831
8321Schema.prototype.virtual = function (name, options) {
8330 var virtuals = this.virtuals;
8340 var parts = name.split('.');
8350 return virtuals[name] = parts.reduce(function (mem, part, i) {
8360 mem[part] || (mem[part] = (i === parts.length-1)
837 ? new VirtualType(options, name)
838 : {});
8390 return mem[part];
840 }, this.tree);
841};
842
843/**
844 * Returns the virtual type with the given `name`.
845 *
846 * @param {String} name
847 * @return {VirtualType}
848 */
849
8501Schema.prototype.virtualpath = function (name) {
8510 return this.virtuals[name];
852};
853
854/*!
855 * Module exports.
856 */
857
8581module.exports = exports = Schema;
859
860// require down here because of reference issues
861
862/**
863 * The various built-in Mongoose Schema Types.
864 *
865 * ####Example:
866 *
867 * var mongoose = require('mongoose');
868 * var ObjectId = mongoose.Schema.Types.ObjectId;
869 *
870 * ####Types:
871 *
872 * - [String](#schema-string-js)
873 * - [Number](#schema-number-js)
874 * - [Boolean](#schema-boolean-js) | Bool
875 * - [Array](#schema-array-js)
876 * - [Buffer](#schema-buffer-js)
877 * - [Date](#schema-date-js)
878 * - [ObjectId](#schema-objectid-js) | Oid
879 * - [Mixed](#schema-mixed-js)
880 *
881 * Using this exposed access to the `Mixed` SchemaType, we can use them in our schema.
882 *
883 * var Mixed = mongoose.Schema.Types.Mixed;
884 * new mongoose.Schema({ _user: Mixed })
885 *
886 * @api public
887 */
888
8891Schema.Types = require('./schema/index');
890
891/*!
892 * ignore
893 */
894
8951Types = Schema.Types;
8961Query = require('./query');
8971var ObjectId = exports.ObjectId = Types.ObjectId;
898
899

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema/array.js

17%
145
25
120
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var SchemaType = require('../schematype')
6 , CastError = SchemaType.CastError
7 , NumberSchema = require('./number')
8 , Types = {
9 Boolean: require('./boolean')
10 , Date: require('./date')
11 , Number: require('./number')
12 , String: require('./string')
13 , ObjectId: require('./objectid')
14 , Buffer: require('./buffer')
15 }
16 , MongooseArray = require('../types').Array
17 , EmbeddedDoc = require('../types').Embedded
18 , Mixed = require('./mixed')
19 , Query = require('../query')
20 , utils = require('../utils')
21 , isMongooseObject = utils.isMongooseObject
22
23/**
24 * Array SchemaType constructor
25 *
26 * @param {String} key
27 * @param {SchemaType} cast
28 * @param {Object} options
29 * @inherits SchemaType
30 * @api private
31 */
32
331function SchemaArray (key, cast, options) {
340 if (cast) {
350 var castOptions = {};
36
370 if ('Object' === cast.constructor.name) {
380 if (cast.type) {
39 // support { type: Woot }
400 castOptions = utils.clone(cast); // do not alter user arguments
410 delete castOptions.type;
420 cast = cast.type;
43 } else {
440 cast = Mixed;
45 }
46 }
47
48 // support { type: 'String' }
490 var name = 'string' == typeof cast
50 ? cast
51 : cast.name;
52
530 var caster = name in Types
54 ? Types[name]
55 : cast;
56
570 this.casterConstructor = caster;
580 this.caster = new caster(null, castOptions);
590 if (!(this.caster instanceof EmbeddedDoc)) {
600 this.caster.path = key;
61 }
62 }
63
640 SchemaType.call(this, key, options);
65
660 var self = this
67 , defaultArr
68 , fn;
69
700 if (this.defaultValue) {
710 defaultArr = this.defaultValue;
720 fn = 'function' == typeof defaultArr;
73 }
74
750 this.default(function(){
760 var arr = fn ? defaultArr() : defaultArr || [];
770 return new MongooseArray(arr, self.path, this);
78 });
79};
80
81/*!
82 * Inherits from SchemaType.
83 */
84
851SchemaArray.prototype.__proto__ = SchemaType.prototype;
86
87/**
88 * Check required
89 *
90 * @param {Array} value
91 * @api private
92 */
93
941SchemaArray.prototype.checkRequired = function (value) {
950 return !!(value && value.length);
96};
97
98/**
99 * Overrides the getters application for the population special-case
100 *
101 * @param {Object} value
102 * @param {Object} scope
103 * @api private
104 */
105
1061SchemaArray.prototype.applyGetters = function (value, scope) {
1070 if (this.caster.options && this.caster.options.ref) {
108 // means the object id was populated
1090 return value;
110 }
111
1120 return SchemaType.prototype.applyGetters.call(this, value, scope);
113};
114
115/**
116 * Casts values for set().
117 *
118 * @param {Object} value
119 * @param {Document} doc document that triggers the casting
120 * @param {Boolean} init whether this is an initialization cast
121 * @api private
122 */
123
1241SchemaArray.prototype.cast = function (value, doc, init) {
1250 if (Array.isArray(value)) {
126
1270 if (!value.length && doc) {
1280 var indexes = doc.schema.indexedPaths();
129
1300 for (var i = 0, l = indexes.length; i < l; ++i) {
1310 var pathIndex = indexes[i][0][this.path];
1320 if ('2dsphere' === pathIndex || '2d' === pathIndex) {
1330 return;
134 }
135 }
136 }
137
1380 if (!(value instanceof MongooseArray)) {
1390 value = new MongooseArray(value, this.path, doc);
140 }
141
1420 if (this.caster) {
1430 try {
1440 for (var i = 0, l = value.length; i < l; i++) {
1450 value[i] = this.caster.cast(value[i], doc, init);
146 }
147 } catch (e) {
148 // rethrow
1490 throw new CastError(e.type, value, this.path);
150 }
151 }
152
1530 return value;
154 } else {
1550 return this.cast([value], doc, init);
156 }
157};
158
159/**
160 * Casts values for queries.
161 *
162 * @param {String} $conditional
163 * @param {any} [value]
164 * @api private
165 */
166
1671SchemaArray.prototype.castForQuery = function ($conditional, value) {
1680 var handler
169 , val;
170
1710 if (arguments.length === 2) {
1720 handler = this.$conditionalHandlers[$conditional];
173
1740 if (!handler) {
1750 throw new Error("Can't use " + $conditional + " with Array.");
176 }
177
1780 val = handler.call(this, value);
179
180 } else {
181
1820 val = $conditional;
1830 var proto = this.casterConstructor.prototype;
1840 var method = proto.castForQuery || proto.cast;
1850 var caster = this.caster;
186
1870 if (Array.isArray(val)) {
1880 val = val.map(function (v) {
1890 if (method) v = method.call(caster, v);
1900 return isMongooseObject(v)
191 ? v.toObject()
192 : v;
193 });
194
1950 } else if (method) {
1960 val = method.call(caster, val);
197 }
198 }
199
2000 return val && isMongooseObject(val)
201 ? val.toObject()
202 : val;
203};
204
205/*!
206 * @ignore
207 *
208 * $atomic cast helpers
209 */
210
2111function castToNumber (val) {
2120 return Types.Number.prototype.cast.call(this, val);
213}
214
2151function castArraysOfNumbers (arr, self) {
2160 self || (self = this);
217
2180 arr.forEach(function (v, i) {
2190 if (Array.isArray(v)) {
2200 castArraysOfNumbers(v, self);
221 } else {
2220 arr[i] = castToNumber.call(self, v);
223 }
224 });
225}
226
2271function cast$near (val) {
2280 if (Array.isArray(val)) {
2290 castArraysOfNumbers(val, this);
2300 return val;
231 }
232
2330 if (val && val.$geometry) {
2340 return cast$geometry(val, this);
235 }
236
2370 return SchemaArray.prototype.castForQuery.call(this, val);
238}
239
2401function cast$geometry (val, self) {
2410 switch (val.$geometry.type) {
242 case 'Polygon':
243 case 'LineString':
244 case 'Point':
2450 castArraysOfNumbers(val.$geometry.coordinates, self);
2460 break;
247 default:
248 // ignore unknowns
2490 break;
250 }
251
2520 if (val.$maxDistance) {
2530 val.$maxDistance = castToNumber.call(self, val.$maxDistance);
254 }
255
2560 return val;
257}
258
2591function cast$within (val) {
2600 var self = this;
261
2620 if (val.$maxDistance) {
2630 val.$maxDistance = castToNumber.call(self, val.$maxDistance);
264 }
265
2660 if (val.$box || val.$polygon) {
2670 var type = val.$box ? '$box' : '$polygon';
2680 val[type].forEach(function (arr) {
2690 if (!Array.isArray(arr)) {
2700 var msg = 'Invalid $within $box argument. '
271 + 'Expected an array, received ' + arr;
2720 throw new TypeError(msg);
273 }
2740 arr.forEach(function (v, i) {
2750 arr[i] = castToNumber.call(this, v);
276 });
277 })
2780 } else if (val.$center || val.$centerSphere) {
2790 var type = val.$center ? '$center' : '$centerSphere';
2800 val[type].forEach(function (item, i) {
2810 if (Array.isArray(item)) {
2820 item.forEach(function (v, j) {
2830 item[j] = castToNumber.call(this, v);
284 });
285 } else {
2860 val[type][i] = castToNumber.call(this, item);
287 }
288 })
2890 } else if (val.$geometry) {
2900 cast$geometry(val, this);
291 }
292
2930 return val;
294}
295
2961function cast$all (val) {
2970 if (!Array.isArray(val)) {
2980 val = [val];
299 }
300
3010 val = val.map(function (v) {
3020 if (utils.isObject(v)) {
3030 var o = {};
3040 o[this.path] = v;
3050 var query = new Query(o);
3060 query.cast(this.casterConstructor);
3070 return query._conditions[this.path];
308 }
3090 return v;
310 }, this);
311
3120 return this.castForQuery(val);
313}
314
3151function cast$elemMatch (val) {
3160 if (val.$in) {
3170 val.$in = this.castForQuery('$in', val.$in);
3180 return val;
319 }
320
3210 var query = new Query(val);
3220 query.cast(this.casterConstructor);
3230 return query._conditions;
324}
325
3261function cast$geoIntersects (val) {
3270 var geo = val.$geometry;
3280 if (!geo) return;
329
3300 cast$geometry(val, this);
3310 return val;
332}
333
3341var handle = SchemaArray.prototype.$conditionalHandlers = {};
335
3361handle.$all = cast$all;
3371handle.$options = String;
3381handle.$elemMatch = cast$elemMatch;
3391handle.$geoIntersects = cast$geoIntersects;
340
3411handle.$near =
342handle.$nearSphere = cast$near;
343
3441handle.$within =
345handle.$geoWithin = cast$within;
346
3471handle.$size =
348handle.$maxDistance = castToNumber;
349
3501handle.$regex =
351handle.$ne =
352handle.$in =
353handle.$nin =
354handle.$gt =
355handle.$gte =
356handle.$lt =
357handle.$lte = SchemaArray.prototype.castForQuery;
358
359/*!
360 * Module exports.
361 */
362
3631module.exports = SchemaArray;
364

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema/boolean.js

38%
26
10
16
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var SchemaType = require('../schematype');
6
7/**
8 * Boolean SchemaType constructor.
9 *
10 * @param {String} path
11 * @param {Object} options
12 * @inherits SchemaType
13 * @api private
14 */
15
161function SchemaBoolean (path, options) {
172 SchemaType.call(this, path, options);
18};
19
20/*!
21 * Inherits from SchemaType.
22 */
231SchemaBoolean.prototype.__proto__ = SchemaType.prototype;
24
25/**
26 * Required validator
27 *
28 * @api private
29 */
30
311SchemaBoolean.prototype.checkRequired = function (value) {
320 return value === true || value === false;
33};
34
35/**
36 * Casts to boolean
37 *
38 * @param {Object} value
39 * @api private
40 */
41
421SchemaBoolean.prototype.cast = function (value) {
430 if (null === value) return value;
440 if ('0' === value) return false;
450 if ('true' === value) return true;
460 if ('false' === value) return false;
470 return !! value;
48}
49
50/*!
51 * ignore
52 */
53
541function handleArray (val) {
550 var self = this;
560 return val.map(function (m) {
570 return self.cast(m);
58 });
59}
60
611SchemaBoolean.$conditionalHandlers = {
62 '$in': handleArray
63}
64
65/**
66 * Casts contents for queries.
67 *
68 * @param {String} $conditional
69 * @param {any} val
70 * @api private
71 */
72
731SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
740 var handler;
750 if (2 === arguments.length) {
760 handler = SchemaBoolean.$conditionalHandlers[$conditional];
77
780 if (handler) {
790 return handler.call(this, val);
80 }
81
820 return this.cast(val);
83 }
84
850 return this.cast($conditional);
86};
87
88/*!
89 * Module exports.
90 */
91
921module.exports = SchemaBoolean;
93

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema/buffer.js

16%
59
10
49
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var SchemaType = require('../schematype')
6 , CastError = SchemaType.CastError
7 , MongooseBuffer = require('../types').Buffer
8 , Binary = MongooseBuffer.Binary
9 , Query = require('../query')
10 , utils = require('../utils')
11 , Document
12
13/**
14 * Buffer SchemaType constructor
15 *
16 * @param {String} key
17 * @param {SchemaType} cast
18 * @inherits SchemaType
19 * @api private
20 */
21
221function SchemaBuffer (key, options) {
230 SchemaType.call(this, key, options, 'Buffer');
24};
25
26/*!
27 * Inherits from SchemaType.
28 */
29
301SchemaBuffer.prototype.__proto__ = SchemaType.prototype;
31
32/**
33 * Check required
34 *
35 * @api private
36 */
37
381SchemaBuffer.prototype.checkRequired = function (value, doc) {
390 if (SchemaType._isRef(this, value, doc, true)) {
400 return null != value;
41 } else {
420 return !!(value && value.length);
43 }
44};
45
46/**
47 * Casts contents
48 *
49 * @param {Object} value
50 * @param {Document} doc document that triggers the casting
51 * @param {Boolean} init
52 * @api private
53 */
54
551SchemaBuffer.prototype.cast = function (value, doc, init) {
560 if (SchemaType._isRef(this, value, doc, init)) {
57 // wait! we may need to cast this to a document
58
590 if (null == value) {
600 return value;
61 }
62
63 // lazy load
640 Document || (Document = require('./../document'));
65
660 if (value instanceof Document) {
670 value.$__.wasPopulated = true;
680 return value;
69 }
70
71 // setting a populated path
720 if (Buffer.isBuffer(value)) {
730 return value;
740 } else if (!utils.isObject(value)) {
750 throw new CastError('buffer', value, this.path);
76 }
77
78 // Handle the case where user directly sets a populated
79 // path to a plain object; cast to the Model used in
80 // the population query.
810 var path = doc.$__fullPath(this.path);
820 var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
830 var pop = owner.populated(path, true);
840 var ret = new pop.options.model(value);
850 ret.$__.wasPopulated = true;
860 return ret;
87 }
88
89 // documents
900 if (value && value._id) {
910 value = value._id;
92 }
93
940 if (Buffer.isBuffer(value)) {
950 if (!(value instanceof MongooseBuffer)) {
960 value = new MongooseBuffer(value, [this.path, doc]);
97 }
98
990 return value;
1000 } else if (value instanceof Binary) {
1010 var ret = new MongooseBuffer(value.value(true), [this.path, doc]);
1020 ret.subtype(value.sub_type);
103 // do not override Binary subtypes. users set this
104 // to whatever they want.
1050 return ret;
106 }
107
1080 if (null === value) return value;
109
1100 var type = typeof value;
1110 if ('string' == type || 'number' == type || Array.isArray(value)) {
1120 var ret = new MongooseBuffer(value, [this.path, doc]);
1130 return ret;
114 }
115
1160 throw new CastError('buffer', value, this.path);
117};
118
119/*!
120 * ignore
121 */
1221function handleSingle (val) {
1230 return this.castForQuery(val);
124}
125
1261function handleArray (val) {
1270 var self = this;
1280 return val.map( function (m) {
1290 return self.castForQuery(m);
130 });
131}
132
1331SchemaBuffer.prototype.$conditionalHandlers = {
134 '$ne' : handleSingle
135 , '$in' : handleArray
136 , '$nin': handleArray
137 , '$gt' : handleSingle
138 , '$lt' : handleSingle
139 , '$gte': handleSingle
140 , '$lte': handleSingle
141};
142
143/**
144 * Casts contents for queries.
145 *
146 * @param {String} $conditional
147 * @param {any} [value]
148 * @api private
149 */
150
1511SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
1520 var handler;
1530 if (arguments.length === 2) {
1540 handler = this.$conditionalHandlers[$conditional];
1550 if (!handler)
1560 throw new Error("Can't use " + $conditional + " with Buffer.");
1570 return handler.call(this, val);
158 } else {
1590 val = $conditional;
1600 return this.cast(val).toObject();
161 }
162};
163
164/*!
165 * Module exports.
166 */
167
1681module.exports = SchemaBuffer;
169

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema/date.js

32%
43
14
29
LineHitsSource
1/*!
2 * Module requirements.
3 */
4
51var SchemaType = require('../schematype');
61var CastError = SchemaType.CastError;
71var utils = require('../utils');
8
9/**
10 * Date SchemaType constructor.
11 *
12 * @param {String} key
13 * @param {Object} options
14 * @inherits SchemaType
15 * @api private
16 */
17
181function SchemaDate (key, options) {
191 SchemaType.call(this, key, options);
20};
21
22/*!
23 * Inherits from SchemaType.
24 */
25
261SchemaDate.prototype.__proto__ = SchemaType.prototype;
27
28/**
29 * Declares a TTL index (rounded to the nearest second) for _Date_ types only.
30 *
31 * This sets the `expiresAfterSeconds` index option available in MongoDB >= 2.1.2.
32 * This index type is only compatible with Date types.
33 *
34 * ####Example:
35 *
36 * // expire in 24 hours
37 * new Schema({ createdAt: { type: Date, expires: 60*60*24 }});
38 *
39 * `expires` utilizes the `ms` module from [guille](https://github.com/guille/) allowing us to use a friendlier syntax:
40 *
41 * ####Example:
42 *
43 * // expire in 24 hours
44 * new Schema({ createdAt: { type: Date, expires: '24h' }});
45 *
46 * // expire in 1.5 hours
47 * new Schema({ createdAt: { type: Date, expires: '1.5h' }});
48 *
49 * // expire in 7 days
50 * var schema = new Schema({ createdAt: Date });
51 * schema.path('createdAt').expires('7d');
52 *
53 * @param {Number|String} when
54 * @added 3.0.0
55 * @return {SchemaType} this
56 * @api public
57 */
58
591SchemaDate.prototype.expires = function (when) {
600 if (!this._index || 'Object' !== this._index.constructor.name) {
610 this._index = {};
62 }
63
640 this._index.expires = when;
650 utils.expires(this._index);
660 return this;
67};
68
69/**
70 * Required validator for date
71 *
72 * @api private
73 */
74
751SchemaDate.prototype.checkRequired = function (value) {
760 return value instanceof Date;
77};
78
79/**
80 * Casts to date
81 *
82 * @param {Object} value to cast
83 * @api private
84 */
85
861SchemaDate.prototype.cast = function (value) {
870 if (value === null || value === '')
880 return null;
89
900 if (value instanceof Date)
910 return value;
92
930 var date;
94
95 // support for timestamps
960 if (value instanceof Number || 'number' == typeof value
97 || String(value) == Number(value))
980 date = new Date(Number(value));
99
100 // support for date strings
1010 else if (value.toString)
1020 date = new Date(value.toString());
103
1040 if (date.toString() != 'Invalid Date')
1050 return date;
106
1070 throw new CastError('date', value, this.path);
108};
109
110/*!
111 * Date Query casting.
112 *
113 * @api private
114 */
115
1161function handleSingle (val) {
1170 return this.cast(val);
118}
119
1201function handleArray (val) {
1210 var self = this;
1220 return val.map( function (m) {
1230 return self.cast(m);
124 });
125}
126
1271SchemaDate.prototype.$conditionalHandlers = {
128 '$lt': handleSingle
129 , '$lte': handleSingle
130 , '$gt': handleSingle
131 , '$gte': handleSingle
132 , '$ne': handleSingle
133 , '$in': handleArray
134 , '$nin': handleArray
135 , '$all': handleArray
136};
137
138
139/**
140 * Casts contents for queries.
141 *
142 * @param {String} $conditional
143 * @param {any} [value]
144 * @api private
145 */
146
1471SchemaDate.prototype.castForQuery = function ($conditional, val) {
1480 var handler;
149
1500 if (2 !== arguments.length) {
1510 return this.cast($conditional);
152 }
153
1540 handler = this.$conditionalHandlers[$conditional];
155
1560 if (!handler) {
1570 throw new Error("Can't use " + $conditional + " with Date.");
158 }
159
1600 return handler.call(this, val);
161};
162
163/*!
164 * Module exports.
165 */
166
1671module.exports = SchemaDate;
168

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema/documentarray.js

10%
67
7
60
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var SchemaType = require('../schematype')
7 , ArrayType = require('./array')
8 , MongooseDocumentArray = require('../types/documentarray')
9 , Subdocument = require('../types/embedded')
10 , Document = require('../document');
11
12/**
13 * SubdocsArray SchemaType constructor
14 *
15 * @param {String} key
16 * @param {Schema} schema
17 * @param {Object} options
18 * @inherits SchemaArray
19 * @api private
20 */
21
221function DocumentArray (key, schema, options) {
23
24 // compile an embedded document for this schema
250 function EmbeddedDocument () {
260 Subdocument.apply(this, arguments);
27 }
28
290 EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
300 EmbeddedDocument.prototype.$__setSchema(schema);
310 EmbeddedDocument.schema = schema;
32
33 // apply methods
340 for (var i in schema.methods) {
350 EmbeddedDocument.prototype[i] = schema.methods[i];
36 }
37
38 // apply statics
390 for (var i in schema.statics)
400 EmbeddedDocument[i] = schema.statics[i];
41
420 EmbeddedDocument.options = options;
430 this.schema = schema;
44
450 ArrayType.call(this, key, EmbeddedDocument, options);
46
470 this.schema = schema;
480 var path = this.path;
490 var fn = this.defaultValue;
50
510 this.default(function(){
520 var arr = fn.call(this);
530 if (!Array.isArray(arr)) arr = [arr];
540 return new MongooseDocumentArray(arr, path, this);
55 });
56};
57
58/*!
59 * Inherits from ArrayType.
60 */
61
621DocumentArray.prototype.__proto__ = ArrayType.prototype;
63
64/**
65 * Performs local validations first, then validations on each embedded doc
66 *
67 * @api private
68 */
69
701DocumentArray.prototype.doValidate = function (array, fn, scope) {
710 var self = this;
72
730 SchemaType.prototype.doValidate.call(this, array, function (err) {
740 if (err) return fn(err);
75
760 var count = array && array.length
77 , error;
78
790 if (!count) return fn();
80
81 // handle sparse arrays, do not use array.forEach which does not
82 // iterate over sparse elements yet reports array.length including
83 // them :(
84
850 for (var i = 0, len = count; i < len; ++i) {
86 // sidestep sparse entries
870 var doc = array[i];
880 if (!doc) {
890 --count || fn();
900 continue;
91 }
92
930 ;(function (i) {
940 doc.validate(function (err) {
950 if (err && !error) {
96 // rewrite the key
970 err.key = self.key + '.' + i + '.' + err.key;
980 return fn(error = err);
99 }
1000 --count || fn();
101 });
102 })(i);
103 }
104 }, scope);
105};
106
107/**
108 * Casts contents
109 *
110 * @param {Object} value
111 * @param {Document} document that triggers the casting
112 * @api private
113 */
114
1151DocumentArray.prototype.cast = function (value, doc, init, prev) {
1160 var selected
117 , subdoc
118 , i
119
1200 if (!Array.isArray(value)) {
1210 return this.cast([value], doc, init, prev);
122 }
123
1240 if (!(value instanceof MongooseDocumentArray)) {
1250 value = new MongooseDocumentArray(value, this.path, doc);
126 }
127
1280 i = value.length;
129
1300 while (i--) {
1310 if (!(value[i] instanceof Subdocument) && value[i]) {
1320 if (init) {
1330 selected || (selected = scopePaths(this, doc.$__.selected, init));
1340 subdoc = new this.casterConstructor(null, value, true, selected);
1350 value[i] = subdoc.init(value[i]);
136 } else {
1370 if (prev && (subdoc = prev.id(value[i]._id))) {
138 // handle resetting doc with existing id but differing data
139 // doc.array = [{ doc: 'val' }]
1400 subdoc.set(value[i]);
141 } else {
1420 subdoc = new this.casterConstructor(value[i], value);
143 }
144
145 // if set() is hooked it will have no return value
146 // see gh-746
1470 value[i] = subdoc;
148 }
149 }
150 }
151
1520 return value;
153}
154
155/*!
156 * Scopes paths selected in a query to this array.
157 * Necessary for proper default application of subdocument values.
158 *
159 * @param {DocumentArray} array - the array to scope `fields` paths
160 * @param {Object|undefined} fields - the root fields selected in the query
161 * @param {Boolean|undefined} init - if we are being created part of a query result
162 */
163
1641function scopePaths (array, fields, init) {
1650 if (!(init && fields)) return undefined;
166
1670 var path = array.path + '.'
168 , keys = Object.keys(fields)
169 , i = keys.length
170 , selected = {}
171 , hasKeys
172 , key
173
1740 while (i--) {
1750 key = keys[i];
1760 if (0 === key.indexOf(path)) {
1770 hasKeys || (hasKeys = true);
1780 selected[key.substring(path.length)] = fields[key];
179 }
180 }
181
1820 return hasKeys && selected || undefined;
183}
184
185/*!
186 * Module exports.
187 */
188
1891module.exports = DocumentArray;
190

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema/index.js

100%
12
12
0
LineHitsSource
1
2/*!
3 * Module exports.
4 */
5
61exports.String = require('./string');
7
81exports.Number = require('./number');
9
101exports.Boolean = require('./boolean');
11
121exports.DocumentArray = require('./documentarray');
13
141exports.Array = require('./array');
15
161exports.Buffer = require('./buffer');
17
181exports.Date = require('./date');
19
201exports.ObjectId = require('./objectid');
21
221exports.Mixed = require('./mixed');
23
24// alias
25
261exports.Oid = exports.ObjectId;
271exports.Object = exports.Mixed;
281exports.Bool = exports.Boolean;
29

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema/mixed.js

50%
20
10
10
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var SchemaType = require('../schematype');
71var utils = require('../utils');
8
9/**
10 * Mixed SchemaType constructor.
11 *
12 * @param {String} path
13 * @param {Object} options
14 * @inherits SchemaType
15 * @api private
16 */
17
181function Mixed (path, options) {
192 if (options && options.default) {
200 var def = options.default;
210 if (Array.isArray(def) && 0 === def.length) {
22 // make sure empty array defaults are handled
230 options.default = Array;
240 } else if (!options.shared &&
25 utils.isObject(def) &&
26 0 === Object.keys(def).length) {
27 // prevent odd "shared" objects between documents
280 options.default = function () {
290 return {}
30 }
31 }
32 }
33
342 SchemaType.call(this, path, options);
35};
36
37/*!
38 * Inherits from SchemaType.
39 */
40
411Mixed.prototype.__proto__ = SchemaType.prototype;
42
43/**
44 * Required validator
45 *
46 * @api private
47 */
48
491Mixed.prototype.checkRequired = function (val) {
500 return (val !== undefined) && (val !== null);
51};
52
53/**
54 * Casts `val` for Mixed.
55 *
56 * _this is a no-op_
57 *
58 * @param {Object} value to cast
59 * @api private
60 */
61
621Mixed.prototype.cast = function (val) {
630 return val;
64};
65
66/**
67 * Casts contents for queries.
68 *
69 * @param {String} $cond
70 * @param {any} [val]
71 * @api private
72 */
73
741Mixed.prototype.castForQuery = function ($cond, val) {
750 if (arguments.length === 2) return val;
760 return $cond;
77};
78
79/*!
80 * Module exports.
81 */
82
831module.exports = Mixed;
84

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema/number.js

17%
73
13
60
LineHitsSource
1/*!
2 * Module requirements.
3 */
4
51var SchemaType = require('../schematype')
6 , CastError = SchemaType.CastError
7 , errorMessages = require('../error').messages
8 , utils = require('../utils')
9 , Document
10
11/**
12 * Number SchemaType constructor.
13 *
14 * @param {String} key
15 * @param {Object} options
16 * @inherits SchemaType
17 * @api private
18 */
19
201function SchemaNumber (key, options) {
217 SchemaType.call(this, key, options, 'Number');
22};
23
24/*!
25 * Inherits from SchemaType.
26 */
27
281SchemaNumber.prototype.__proto__ = SchemaType.prototype;
29
30/**
31 * Required validator for number
32 *
33 * @api private
34 */
35
361SchemaNumber.prototype.checkRequired = function checkRequired (value, doc) {
370 if (SchemaType._isRef(this, value, doc, true)) {
380 return null != value;
39 } else {
400 return typeof value == 'number' || value instanceof Number;
41 }
42};
43
44/**
45 * Sets a minimum number validator.
46 *
47 * ####Example:
48 *
49 * var s = new Schema({ n: { type: Number, min: 10 })
50 * var M = db.model('M', s)
51 * var m = new M({ n: 9 })
52 * m.save(function (err) {
53 * console.error(err) // validator error
54 * m.n = 10;
55 * m.save() // success
56 * })
57 *
58 * // custom error messages
59 * // We can also use the special {MIN} token which will be replaced with the invalid value
60 * var min = [10, 'The value of path `{PATH}` ({VALUE}) is beneath the limit ({MIN}).'];
61 * var schema = new Schema({ n: { type: Number, min: min })
62 * var M = mongoose.model('Measurement', schema);
63 * var s= new M({ n: 4 });
64 * s.validate(function (err) {
65 * console.log(String(err)) // ValidationError: The value of path `n` (4) is beneath the limit (10).
66 * })
67 *
68 * @param {Number} value minimum number
69 * @param {String} [message] optional custom error message
70 * @return {SchemaType} this
71 * @see Customized Error Messages #error_messages_MongooseError-messages
72 * @api public
73 */
74
751SchemaNumber.prototype.min = function (value, message) {
760 if (this.minValidator) {
770 this.validators = this.validators.filter(function (v) {
780 return v[0] != this.minValidator;
79 }, this);
80 }
81
820 if (null != value) {
830 var msg = message || errorMessages.Number.min;
840 msg = msg.replace(/{MIN}/, value);
850 this.validators.push([this.minValidator = function (v) {
860 return v === null || v >= value;
87 }, msg, 'min']);
88 }
89
900 return this;
91};
92
93/**
94 * Sets a maximum number validator.
95 *
96 * ####Example:
97 *
98 * var s = new Schema({ n: { type: Number, max: 10 })
99 * var M = db.model('M', s)
100 * var m = new M({ n: 11 })
101 * m.save(function (err) {
102 * console.error(err) // validator error
103 * m.n = 10;
104 * m.save() // success
105 * })
106 *
107 * // custom error messages
108 * // We can also use the special {MAX} token which will be replaced with the invalid value
109 * var max = [10, 'The value of path `{PATH}` ({VALUE}) exceeds the limit ({MAX}).'];
110 * var schema = new Schema({ n: { type: Number, max: max })
111 * var M = mongoose.model('Measurement', schema);
112 * var s= new M({ n: 4 });
113 * s.validate(function (err) {
114 * console.log(String(err)) // ValidationError: The value of path `n` (4) exceeds the limit (10).
115 * })
116 *
117 * @param {Number} maximum number
118 * @param {String} [message] optional custom error message
119 * @return {SchemaType} this
120 * @see Customized Error Messages #error_messages_MongooseError-messages
121 * @api public
122 */
123
1241SchemaNumber.prototype.max = function (value, message) {
1250 if (this.maxValidator) {
1260 this.validators = this.validators.filter(function(v){
1270 return v[0] != this.maxValidator;
128 }, this);
129 }
130
1310 if (null != value) {
1320 var msg = message || errorMessages.Number.max;
1330 msg = msg.replace(/{MAX}/, value);
1340 this.validators.push([this.maxValidator = function(v){
1350 return v === null || v <= value;
136 }, msg, 'max']);
137 }
138
1390 return this;
140};
141
142/**
143 * Casts to number
144 *
145 * @param {Object} value value to cast
146 * @param {Document} doc document that triggers the casting
147 * @param {Boolean} init
148 * @api private
149 */
150
1511SchemaNumber.prototype.cast = function (value, doc, init) {
1520 if (SchemaType._isRef(this, value, doc, init)) {
153 // wait! we may need to cast this to a document
154
1550 if (null == value) {
1560 return value;
157 }
158
159 // lazy load
1600 Document || (Document = require('./../document'));
161
1620 if (value instanceof Document) {
1630 value.$__.wasPopulated = true;
1640 return value;
165 }
166
167 // setting a populated path
1680 if ('number' == typeof value) {
1690 return value;
1700 } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
1710 throw new CastError('number', value, this.path);
172 }
173
174 // Handle the case where user directly sets a populated
175 // path to a plain object; cast to the Model used in
176 // the population query.
1770 var path = doc.$__fullPath(this.path);
1780 var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
1790 var pop = owner.populated(path, true);
1800 var ret = new pop.options.model(value);
1810 ret.$__.wasPopulated = true;
1820 return ret;
183 }
184
1850 var val = value && value._id
186 ? value._id // documents
187 : value;
188
1890 if (!isNaN(val)){
1900 if (null === val) return val;
1910 if ('' === val) return null;
1920 if ('string' == typeof val) val = Number(val);
1930 if (val instanceof Number) return val
1940 if ('number' == typeof val) return val;
1950 if (val.toString && !Array.isArray(val) &&
196 val.toString() == Number(val)) {
1970 return new Number(val)
198 }
199 }
200
2010 throw new CastError('number', value, this.path);
202};
203
204/*!
205 * ignore
206 */
207
2081function handleSingle (val) {
2090 return this.cast(val)
210}
211
2121function handleArray (val) {
2130 var self = this;
2140 return val.map(function (m) {
2150 return self.cast(m)
216 });
217}
218
2191SchemaNumber.prototype.$conditionalHandlers = {
220 '$lt' : handleSingle
221 , '$lte': handleSingle
222 , '$gt' : handleSingle
223 , '$gte': handleSingle
224 , '$ne' : handleSingle
225 , '$in' : handleArray
226 , '$nin': handleArray
227 , '$mod': handleArray
228 , '$all': handleArray
229};
230
231/**
232 * Casts contents for queries.
233 *
234 * @param {String} $conditional
235 * @param {any} [value]
236 * @api private
237 */
238
2391SchemaNumber.prototype.castForQuery = function ($conditional, val) {
2400 var handler;
2410 if (arguments.length === 2) {
2420 handler = this.$conditionalHandlers[$conditional];
2430 if (!handler)
2440 throw new Error("Can't use " + $conditional + " with Number.");
2450 return handler.call(this, val);
246 } else {
2470 val = this.cast($conditional);
2480 return val == null ? val : val
249 }
250};
251
252/*!
253 * Module exports.
254 */
255
2561module.exports = SchemaNumber;
257

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema/objectid.js

20%
62
13
49
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var SchemaType = require('../schematype')
6 , CastError = SchemaType.CastError
7 , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'
8 , oid = require('../types/objectid')
9 , utils = require('../utils')
10 , Document
11
12/**
13 * ObjectId SchemaType constructor.
14 *
15 * @param {String} key
16 * @param {Object} options
17 * @inherits SchemaType
18 * @api private
19 */
20
211function ObjectId (key, options) {
220 SchemaType.call(this, key, options, 'ObjectID');
23};
24
25/*!
26 * Inherits from SchemaType.
27 */
28
291ObjectId.prototype.__proto__ = SchemaType.prototype;
30
31/**
32 * Adds an auto-generated ObjectId default if turnOn is true.
33 * @param {Boolean} turnOn auto generated ObjectId defaults
34 * @api public
35 * @return {SchemaType} this
36 */
37
381ObjectId.prototype.auto = function (turnOn) {
390 if (turnOn) {
400 this.default(defaultId);
410 this.set(resetId)
42 }
43
440 return this;
45};
46
47/**
48 * Check required
49 *
50 * @api private
51 */
52
531ObjectId.prototype.checkRequired = function checkRequired (value, doc) {
540 if (SchemaType._isRef(this, value, doc, true)) {
550 return null != value;
56 } else {
570 return value instanceof oid;
58 }
59};
60
61/**
62 * Casts to ObjectId
63 *
64 * @param {Object} value
65 * @param {Object} doc
66 * @param {Boolean} init whether this is an initialization cast
67 * @api private
68 */
69
701ObjectId.prototype.cast = function (value, doc, init) {
710 if (SchemaType._isRef(this, value, doc, init)) {
72 // wait! we may need to cast this to a document
73
740 if (null == value) {
750 return value;
76 }
77
78 // lazy load
790 Document || (Document = require('./../document'));
80
810 if (value instanceof Document) {
820 value.$__.wasPopulated = true;
830 return value;
84 }
85
86 // setting a populated path
870 if (value instanceof oid) {
880 return value;
890 } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
900 throw new CastError('ObjectId', value, this.path);
91 }
92
93 // Handle the case where user directly sets a populated
94 // path to a plain object; cast to the Model used in
95 // the population query.
960 var path = doc.$__fullPath(this.path);
970 var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
980 var pop = owner.populated(path, true);
990 var ret = new pop.options.model(value);
1000 ret.$__.wasPopulated = true;
1010 return ret;
102 }
103
1040 if (value === null) return value;
105
1060 if (value instanceof oid)
1070 return value;
108
1090 if (value._id && value._id instanceof oid)
1100 return value._id;
111
1120 if (value.toString) {
1130 try {
1140 return oid.createFromHexString(value.toString());
115 } catch (err) {
1160 throw new CastError('ObjectId', value, this.path);
117 }
118 }
119
1200 throw new CastError('ObjectId', value, this.path);
121};
122
123/*!
124 * ignore
125 */
126
1271function handleSingle (val) {
1280 return this.cast(val);
129}
130
1311function handleArray (val) {
1320 var self = this;
1330 return val.map(function (m) {
1340 return self.cast(m);
135 });
136}
137
1381ObjectId.prototype.$conditionalHandlers = {
139 '$ne': handleSingle
140 , '$in': handleArray
141 , '$nin': handleArray
142 , '$gt': handleSingle
143 , '$lt': handleSingle
144 , '$gte': handleSingle
145 , '$lte': handleSingle
146 , '$all': handleArray
147};
148
149/**
150 * Casts contents for queries.
151 *
152 * @param {String} $conditional
153 * @param {any} [val]
154 * @api private
155 */
156
1571ObjectId.prototype.castForQuery = function ($conditional, val) {
1580 var handler;
1590 if (arguments.length === 2) {
1600 handler = this.$conditionalHandlers[$conditional];
1610 if (!handler)
1620 throw new Error("Can't use " + $conditional + " with ObjectId.");
1630 return handler.call(this, val);
164 } else {
1650 return this.cast($conditional);
166 }
167};
168
169/*!
170 * ignore
171 */
172
1731function defaultId () {
1740 return new oid();
175};
176
1771function resetId (v) {
1780 this.$__._id = null;
1790 return v;
180}
181
182/*!
183 * Module exports.
184 */
185
1861module.exports = ObjectId;
187

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schema/string.js

18%
97
18
79
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var SchemaType = require('../schematype')
7 , CastError = SchemaType.CastError
8 , errorMessages = require('../error').messages
9 , utils = require('../utils')
10 , Document
11
12/**
13 * String SchemaType constructor.
14 *
15 * @param {String} key
16 * @param {Object} options
17 * @inherits SchemaType
18 * @api private
19 */
20
211function SchemaString (key, options) {
225 this.enumValues = [];
235 this.regExp = null;
245 SchemaType.call(this, key, options, 'String');
25};
26
27/*!
28 * Inherits from SchemaType.
29 */
30
311SchemaString.prototype.__proto__ = SchemaType.prototype;
32
33/**
34 * Adds an enum validator
35 *
36 * ####Example:
37 *
38 * var states = 'opening open closing closed'.split(' ')
39 * var s = new Schema({ state: { type: String, enum: states }})
40 * var M = db.model('M', s)
41 * var m = new M({ state: 'invalid' })
42 * m.save(function (err) {
43 * console.error(String(err)) // ValidationError: `invalid` is not a valid enum value for path `state`.
44 * m.state = 'open'
45 * m.save(callback) // success
46 * })
47 *
48 * // or with custom error messages
49 * var enu = {
50 * values: 'opening open closing closed'.split(' '),
51 * message: 'enum validator failed for path `{PATH}` with value `{VALUE}`'
52 * }
53 * var s = new Schema({ state: { type: String, enum: enu })
54 * var M = db.model('M', s)
55 * var m = new M({ state: 'invalid' })
56 * m.save(function (err) {
57 * console.error(String(err)) // ValidationError: enum validator failed for path `state` with value `invalid`
58 * m.state = 'open'
59 * m.save(callback) // success
60 * })
61 *
62 * @param {String|Object} [args...] enumeration values
63 * @return {SchemaType} this
64 * @see Customized Error Messages #error_messages_MongooseError-messages
65 * @api public
66 */
67
681SchemaString.prototype.enum = function () {
690 if (this.enumValidator) {
700 this.validators = this.validators.filter(function(v){
710 return v[0] != this.enumValidator;
72 }, this);
730 this.enumValidator = false;
74 }
75
760 if (undefined === arguments[0] || false === arguments[0]) {
770 return this;
78 }
79
800 var values;
810 var errorMessage;
82
830 if (utils.isObject(arguments[0])) {
840 values = arguments[0].values;
850 errorMessage = arguments[0].message;
86 } else {
870 values = arguments;
880 errorMessage = errorMessages.String.enum;
89 }
90
910 for (var i = 0; i < values.length; i++) {
920 if (undefined !== values[i]) {
930 this.enumValues.push(this.cast(values[i]));
94 }
95 }
96
970 var vals = this.enumValues;
980 this.enumValidator = function (v) {
990 return undefined === v || ~vals.indexOf(v);
100 };
1010 this.validators.push([this.enumValidator, errorMessage, 'enum']);
102
1030 return this;
104};
105
106/**
107 * Adds a lowercase setter.
108 *
109 * ####Example:
110 *
111 * var s = new Schema({ email: { type: String, lowercase: true }})
112 * var M = db.model('M', s);
113 * var m = new M({ email: 'SomeEmail@example.COM' });
114 * console.log(m.email) // someemail@example.com
115 *
116 * @api public
117 * @return {SchemaType} this
118 */
119
1201SchemaString.prototype.lowercase = function () {
1210 return this.set(function (v, self) {
1220 if ('string' != typeof v) v = self.cast(v)
1230 if (v) return v.toLowerCase();
1240 return v;
125 });
126};
127
128/**
129 * Adds an uppercase setter.
130 *
131 * ####Example:
132 *
133 * var s = new Schema({ caps: { type: String, uppercase: true }})
134 * var M = db.model('M', s);
135 * var m = new M({ caps: 'an example' });
136 * console.log(m.caps) // AN EXAMPLE
137 *
138 * @api public
139 * @return {SchemaType} this
140 */
141
1421SchemaString.prototype.uppercase = function () {
1430 return this.set(function (v, self) {
1440 if ('string' != typeof v) v = self.cast(v)
1450 if (v) return v.toUpperCase();
1460 return v;
147 });
148};
149
150/**
151 * Adds a trim setter.
152 *
153 * The string value will be trimmed when set.
154 *
155 * ####Example:
156 *
157 * var s = new Schema({ name: { type: String, trim: true }})
158 * var M = db.model('M', s)
159 * var string = ' some name '
160 * console.log(string.length) // 11
161 * var m = new M({ name: string })
162 * console.log(m.name.length) // 9
163 *
164 * @api public
165 * @return {SchemaType} this
166 */
167
1681SchemaString.prototype.trim = function () {
1690 return this.set(function (v, self) {
1700 if ('string' != typeof v) v = self.cast(v)
1710 if (v) return v.trim();
1720 return v;
173 });
174};
175
176/**
177 * Sets a regexp validator.
178 *
179 * Any value that does not pass `regExp`.test(val) will fail validation.
180 *
181 * ####Example:
182 *
183 * var s = new Schema({ name: { type: String, match: /^a/ }})
184 * var M = db.model('M', s)
185 * var m = new M({ name: 'I am invalid' })
186 * m.validate(function (err) {
187 * console.error(String(err)) // "ValidationError: Path `name` is invalid (I am invalid)."
188 * m.name = 'apples'
189 * m.validate(function (err) {
190 * assert.ok(err) // success
191 * })
192 * })
193 *
194 * // using a custom error message
195 * var match = [ /\.html$/, "That file doesn't end in .html ({VALUE})" ];
196 * var s = new Schema({ file: { type: String, match: match }})
197 * var M = db.model('M', s);
198 * var m = new M({ file: 'invalid' });
199 * m.validate(function (err) {
200 * console.log(String(err)) // "ValidationError: That file doesn't end in .html (invalid)"
201 * })
202 *
203 * Empty strings, `undefined`, and `null` values always pass the match validator. If you require these values, enable the `required` validator also.
204 *
205 * var s = new Schema({ name: { type: String, match: /^a/, required: true }})
206 *
207 * @param {RegExp} regExp regular expression to test against
208 * @param {String} [message] optional custom error message
209 * @return {SchemaType} this
210 * @see Customized Error Messages #error_messages_MongooseError-messages
211 * @api public
212 */
213
2141SchemaString.prototype.match = function match (regExp, message) {
215 // yes, we allow multiple match validators
216
2170 var msg = message || errorMessages.String.match;
218
2190 function matchValidator (v){
2200 return null != v && '' !== v
221 ? regExp.test(v)
222 : true
223 }
224
2250 this.validators.push([matchValidator, msg, 'regexp']);
2260 return this;
227};
228
229/**
230 * Check required
231 *
232 * @param {String|null|undefined} value
233 * @api private
234 */
235
2361SchemaString.prototype.checkRequired = function checkRequired (value, doc) {
2370 if (SchemaType._isRef(this, value, doc, true)) {
2380 return null != value;
239 } else {
2400 return (value instanceof String || typeof value == 'string') && value.length;
241 }
242};
243
244/**
245 * Casts to String
246 *
247 * @api private
248 */
249
2501SchemaString.prototype.cast = function (value, doc, init) {
2510 if (SchemaType._isRef(this, value, doc, init)) {
252 // wait! we may need to cast this to a document
253
2540 if (null == value) {
2550 return value;
256 }
257
258 // lazy load
2590 Document || (Document = require('./../document'));
260
2610 if (value instanceof Document) {
2620 value.$__.wasPopulated = true;
2630 return value;
264 }
265
266 // setting a populated path
2670 if ('string' == typeof value) {
2680 return value;
2690 } else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
2700 throw new CastError('string', value, this.path);
271 }
272
273 // Handle the case where user directly sets a populated
274 // path to a plain object; cast to the Model used in
275 // the population query.
2760 var path = doc.$__fullPath(this.path);
2770 var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
2780 var pop = owner.populated(path, true);
2790 var ret = new pop.options.model(value);
2800 ret.$__.wasPopulated = true;
2810 return ret;
282 }
283
2840 if (value === null) {
2850 return value;
286 }
287
2880 if ('undefined' !== typeof value) {
289 // handle documents being passed
2900 if (value._id && 'string' == typeof value._id) {
2910 return value._id;
292 }
2930 if (value.toString) {
2940 return value.toString();
295 }
296 }
297
298
2990 throw new CastError('string', value, this.path);
300};
301
302/*!
303 * ignore
304 */
305
3061function handleSingle (val) {
3070 return this.castForQuery(val);
308}
309
3101function handleArray (val) {
3110 var self = this;
3120 return val.map(function (m) {
3130 return self.castForQuery(m);
314 });
315}
316
3171SchemaString.prototype.$conditionalHandlers = {
318 '$ne' : handleSingle
319 , '$in' : handleArray
320 , '$nin': handleArray
321 , '$gt' : handleSingle
322 , '$lt' : handleSingle
323 , '$gte': handleSingle
324 , '$lte': handleSingle
325 , '$all': handleArray
326 , '$regex': handleSingle
327 , '$options': handleSingle
328};
329
330/**
331 * Casts contents for queries.
332 *
333 * @param {String} $conditional
334 * @param {any} [val]
335 * @api private
336 */
337
3381SchemaString.prototype.castForQuery = function ($conditional, val) {
3390 var handler;
3400 if (arguments.length === 2) {
3410 handler = this.$conditionalHandlers[$conditional];
3420 if (!handler)
3430 throw new Error("Can't use " + $conditional + " with String.");
3440 return handler.call(this, val);
345 } else {
3460 val = $conditional;
3470 if (val instanceof RegExp) return val;
3480 return this.cast(val);
349 }
350};
351
352/*!
353 * Module exports.
354 */
355
3561module.exports = SchemaString;
357

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schemadefault.js

100%
2
2
0
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var Schema = require('./schema')
7
8/**
9 * Default model for querying the system.profiles collection.
10 *
11 * @property system.profile
12 * @receiver exports
13 * @api private
14 */
15
161exports['system.profile'] = new Schema({
17 ts: Date
18 , info: String // deprecated
19 , millis: Number
20 , op: String
21 , ns: String
22 , query: Schema.Types.Mixed
23 , updateobj: Schema.Types.Mixed
24 , ntoreturn: Number
25 , nreturned: Number
26 , nscanned: Number
27 , responseLength: Number
28 , client: String
29 , user: String
30 , idhack: Boolean
31 , scanAndOrder: Boolean
32 , keyUpdates: Number
33 , cursorid: Number
34}, { noVirtualId: true, noId: true });
35

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/schematype.js

22%
143
32
111
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var utils = require('./utils');
61var error = require('./error');
71var errorMessages = error.messages;
81var CastError = error.CastError;
91var ValidatorError = error.ValidatorError;
10
11/**
12 * SchemaType constructor
13 *
14 * @param {String} path
15 * @param {Object} [options]
16 * @param {String} [instance]
17 * @api public
18 */
19
201function SchemaType (path, options, instance) {
2117 this.path = path;
2217 this.instance = instance;
2317 this.validators = [];
2417 this.setters = [];
2517 this.getters = [];
2617 this.options = options;
2717 this._index = null;
2817 this.selected;
29
3034 for (var i in options) if (this[i] && 'function' == typeof this[i]) {
31 // { unique: true, index: true }
320 if ('index' == i && this._index) continue;
33
340 var opts = Array.isArray(options[i])
35 ? options[i]
36 : [options[i]];
37
380 this[i].apply(this, opts);
39 }
40};
41
42/**
43 * Sets a default value for this SchemaType.
44 *
45 * ####Example:
46 *
47 * var schema = new Schema({ n: { type: Number, default: 10 })
48 * var M = db.model('M', schema)
49 * var m = new M;
50 * console.log(m.n) // 10
51 *
52 * Defaults can be either `functions` which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.
53 *
54 * ####Example:
55 *
56 * // values are cast:
57 * var schema = new Schema({ aNumber: Number, default: "4.815162342" })
58 * var M = db.model('M', schema)
59 * var m = new M;
60 * console.log(m.aNumber) // 4.815162342
61 *
62 * // default unique objects for Mixed types:
63 * var schema = new Schema({ mixed: Schema.Types.Mixed });
64 * schema.path('mixed').default(function () {
65 * return {};
66 * });
67 *
68 * // if we don't use a function to return object literals for Mixed defaults,
69 * // each document will receive a reference to the same object literal creating
70 * // a "shared" object instance:
71 * var schema = new Schema({ mixed: Schema.Types.Mixed });
72 * schema.path('mixed').default({});
73 * var M = db.model('M', schema);
74 * var m1 = new M;
75 * m1.mixed.added = 1;
76 * console.log(m1.mixed); // { added: 1 }
77 * var m2 = new M;
78 * console.log(m2.mixed); // { added: 1 }
79 *
80 * @param {Function|any} val the default value
81 * @return {defaultValue}
82 * @api public
83 */
84
851SchemaType.prototype.default = function (val) {
860 if (1 === arguments.length) {
870 this.defaultValue = typeof val === 'function'
88 ? val
89 : this.cast(val);
900 return this;
910 } else if (arguments.length > 1) {
920 this.defaultValue = utils.args(arguments);
93 }
940 return this.defaultValue;
95};
96
97/**
98 * Declares the index options for this schematype.
99 *
100 * ####Example:
101 *
102 * var s = new Schema({ name: { type: String, index: true })
103 * var s = new Schema({ loc: { type: [Number], index: 'hashed' })
104 * var s = new Schema({ loc: { type: [Number], index: '2d', sparse: true })
105 * var s = new Schema({ loc: { type: [Number], index: { type: '2dsphere', sparse: true }})
106 * var s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})
107 * Schema.path('my.path').index(true);
108 * Schema.path('my.date').index({ expires: 60 });
109 * Schema.path('my.path').index({ unique: true, sparse: true });
110 *
111 * ####NOTE:
112 *
113 * _Indexes are created in the background by default. Specify `background: false` to override._
114 *
115 * [Direction doesn't matter for single key indexes](http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeysIndexes)
116 *
117 * @param {Object|Boolean|String} options
118 * @return {SchemaType} this
119 * @api public
120 */
121
1221SchemaType.prototype.index = function (options) {
1230 this._index = options;
1240 utils.expires(this._index);
1250 return this;
126};
127
128/**
129 * Declares an unique index.
130 *
131 * ####Example:
132 *
133 * var s = new Schema({ name: { type: String, unique: true })
134 * Schema.path('name').index({ unique: true });
135 *
136 * _NOTE: violating the constraint returns an `E11000` error from MongoDB when saving, not a Mongoose validation error._
137 *
138 * @param {Boolean} bool
139 * @return {SchemaType} this
140 * @api public
141 */
142
1431SchemaType.prototype.unique = function (bool) {
1440 if (null == this._index || 'boolean' == typeof this._index) {
1450 this._index = {};
1460 } else if ('string' == typeof this._index) {
1470 this._index = { type: this._index };
148 }
149
1500 this._index.unique = bool;
1510 return this;
152};
153
154/**
155 * Declares a sparse index.
156 *
157 * ####Example:
158 *
159 * var s = new Schema({ name: { type: String, sparse: true })
160 * Schema.path('name').index({ sparse: true });
161 *
162 * @param {Boolean} bool
163 * @return {SchemaType} this
164 * @api public
165 */
166
1671SchemaType.prototype.sparse = function (bool) {
1680 if (null == this._index || 'boolean' == typeof this._index) {
1690 this._index = {};
1700 } else if ('string' == typeof this._index) {
1710 this._index = { type: this._index };
172 }
173
1740 this._index.sparse = bool;
1750 return this;
176};
177
178/**
179 * Adds a setter to this schematype.
180 *
181 * ####Example:
182 *
183 * function capitalize (val) {
184 * if ('string' != typeof val) val = '';
185 * return val.charAt(0).toUpperCase() + val.substring(1);
186 * }
187 *
188 * // defining within the schema
189 * var s = new Schema({ name: { type: String, set: capitalize }})
190 *
191 * // or by retreiving its SchemaType
192 * var s = new Schema({ name: String })
193 * s.path('name').set(capitalize)
194 *
195 * Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.
196 *
197 * Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.
198 *
199 * You can set up email lower case normalization easily via a Mongoose setter.
200 *
201 * function toLower (v) {
202 * return v.toLowerCase();
203 * }
204 *
205 * var UserSchema = new Schema({
206 * email: { type: String, set: toLower }
207 * })
208 *
209 * var User = db.model('User', UserSchema)
210 *
211 * var user = new User({email: 'AVENUE@Q.COM'})
212 * console.log(user.email); // 'avenue@q.com'
213 *
214 * // or
215 * var user = new User
216 * user.email = 'Avenue@Q.com'
217 * console.log(user.email) // 'avenue@q.com'
218 *
219 * As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.
220 *
221 * _NOTE: we could have also just used the built-in `lowercase: true` SchemaType option instead of defining our own function._
222 *
223 * new Schema({ email: { type: String, lowercase: true }})
224 *
225 * Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.
226 *
227 * function inspector (val, schematype) {
228 * if (schematype.options.required) {
229 * return schematype.path + ' is required';
230 * } else {
231 * return val;
232 * }
233 * }
234 *
235 * var VirusSchema = new Schema({
236 * name: { type: String, required: true, set: inspector },
237 * taxonomy: { type: String, set: inspector }
238 * })
239 *
240 * var Virus = db.model('Virus', VirusSchema);
241 * var v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });
242 *
243 * console.log(v.name); // name is required
244 * console.log(v.taxonomy); // Parvovirinae
245 *
246 * @param {Function} fn
247 * @return {SchemaType} this
248 * @api public
249 */
250
2511SchemaType.prototype.set = function (fn) {
2520 if ('function' != typeof fn)
2530 throw new TypeError('A setter must be a function.');
2540 this.setters.push(fn);
2550 return this;
256};
257
258/**
259 * Adds a getter to this schematype.
260 *
261 * ####Example:
262 *
263 * function dob (val) {
264 * if (!val) return val;
265 * return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
266 * }
267 *
268 * // defining within the schema
269 * var s = new Schema({ born: { type: Date, get: dob })
270 *
271 * // or by retreiving its SchemaType
272 * var s = new Schema({ born: Date })
273 * s.path('born').get(dob)
274 *
275 * Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.
276 *
277 * Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:
278 *
279 * function obfuscate (cc) {
280 * return '****-****-****-' + cc.slice(cc.length-4, cc.length);
281 * }
282 *
283 * var AccountSchema = new Schema({
284 * creditCardNumber: { type: String, get: obfuscate }
285 * });
286 *
287 * var Account = db.model('Account', AccountSchema);
288 *
289 * Account.findById(id, function (err, found) {
290 * console.log(found.creditCardNumber); // '****-****-****-1234'
291 * });
292 *
293 * Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema.
294 *
295 * function inspector (val, schematype) {
296 * if (schematype.options.required) {
297 * return schematype.path + ' is required';
298 * } else {
299 * return schematype.path + ' is not';
300 * }
301 * }
302 *
303 * var VirusSchema = new Schema({
304 * name: { type: String, required: true, get: inspector },
305 * taxonomy: { type: String, get: inspector }
306 * })
307 *
308 * var Virus = db.model('Virus', VirusSchema);
309 *
310 * Virus.findById(id, function (err, virus) {
311 * console.log(virus.name); // name is required
312 * console.log(virus.taxonomy); // taxonomy is not
313 * })
314 *
315 * @param {Function} fn
316 * @return {SchemaType} this
317 * @api public
318 */
319
3201SchemaType.prototype.get = function (fn) {
3210 if ('function' != typeof fn)
3220 throw new TypeError('A getter must be a function.');
3230 this.getters.push(fn);
3240 return this;
325};
326
327/**
328 * Adds validator(s) for this document path.
329 *
330 * Validators always receive the value to validate as their first argument and must return `Boolean`. Returning `false` means validation failed.
331 *
332 * The error message argument is optional. If not passed, the [default generic error message template](#error_messages_MongooseError-messages) will be used.
333 *
334 * ####Examples:
335 *
336 * // make sure every value is equal to "something"
337 * function validator (val) {
338 * return val == 'something';
339 * }
340 * new Schema({ name: { type: String, validate: validator }});
341 *
342 * // with a custom error message
343 *
344 * var custom = [validator, 'Uh oh, {PATH} does not equal "something".']
345 * new Schema({ name: { type: String, validate: custom }});
346 *
347 * // adding many validators at a time
348 *
349 * var many = [
350 * { validator: validator, msg: 'uh oh' }
351 * , { validator: anotherValidator, msg: 'failed' }
352 * ]
353 * new Schema({ name: { type: String, validate: many }});
354 *
355 * // or utilizing SchemaType methods directly:
356 *
357 * var schema = new Schema({ name: 'string' });
358 * schema.path('name').validate(validator, 'validation of `{PATH}` failed with value `{VALUE}`');
359 *
360 * ####Error message templates:
361 *
362 * From the examples above, you may have noticed that error messages support baseic templating. There are a few other template keywords besides `{PATH}` and `{VALUE}` too. To find out more, details are available [here](#error_messages_MongooseError-messages)
363 *
364 * ####Asynchronous validation:
365 *
366 * Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first argument passed to the validator function is the value being validated. The second argument is a callback function that must called when you finish validating the value and passed either `true` or `false` to communicate either success or failure respectively.
367 *
368 * schema.path('name').validate(function (value, respond) {
369 * doStuff(value, function () {
370 * ...
371 * respond(false); // validation failed
372 * })
373* }, '{PATH} failed validation.');
374*
375 * You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs.
376 *
377 * Validation occurs `pre('save')` or whenever you manually execute [document#validate](#document_Document-validate).
378 *
379 * If validation fails during `pre('save')` and no callback was passed to receive the error, an `error` event will be emitted on your Models associated db [connection](#connection_Connection), passing the validation error object along.
380 *
381 * var conn = mongoose.createConnection(..);
382 * conn.on('error', handleError);
383 *
384 * var Product = conn.model('Product', yourSchema);
385 * var dvd = new Product(..);
386 * dvd.save(); // emits error on the `conn` above
387 *
388 * If you desire handling these errors at the Model level, attach an `error` listener to your Model and the event will instead be emitted there.
389 *
390 * // registering an error listener on the Model lets us handle errors more locally
391 * Product.on('error', handleError);
392 *
393 * @param {RegExp|Function|Object} obj validator
394 * @param {String} [errorMsg] optional error message
395 * @return {SchemaType} this
396 * @api public
397 */
398
3991SchemaType.prototype.validate = function (obj, message) {
4000 if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
4010 if (!message) message = errorMessages.general.default;
4020 this.validators.push([obj, message, 'user defined']);
4030 return this;
404 }
405
4060 var i = arguments.length
407 , arg
408
4090 while (i--) {
4100 arg = arguments[i];
4110 if (!(arg && 'Object' == arg.constructor.name)) {
4120 var msg = 'Invalid validator. Received (' + typeof arg + ') '
413 + arg
414 + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
415
4160 throw new Error(msg);
417 }
4180 this.validate(arg.validator, arg.msg);
419 }
420
4210 return this;
422};
423
424/**
425 * Adds a required validator to this schematype.
426 *
427 * ####Example:
428 *
429 * var s = new Schema({ born: { type: Date, required: true })
430 *
431 * // or with custom error message
432 *
433 * var s = new Schema({ born: { type: Date, required: '{PATH} is required!' })
434 *
435 * // or through the path API
436 *
437 * Schema.path('name').required(true);
438 *
439 * // with custom error messaging
440 *
441 * Schema.path('name').required(true, 'grrr :( ');
442 *
443 *
444 * @param {Boolean} required enable/disable the validator
445 * @param {String} [message] optional custom error message
446 * @return {SchemaType} this
447 * @see Customized Error Messages #error_messages_MongooseError-messages
448 * @api public
449 */
450
4511SchemaType.prototype.required = function (required, message) {
4520 if (false === required) {
4530 this.validators = this.validators.filter(function (v) {
4540 return v[0] != this.requiredValidator;
455 }, this);
456
4570 this.isRequired = false;
4580 return this;
459 }
460
4610 var self = this;
4620 this.isRequired = true;
463
4640 this.requiredValidator = function (v) {
465 // in here, `this` refers to the validating document.
466 // no validation when this path wasn't selected in the query.
4670 if ('isSelected' in this &&
468 !this.isSelected(self.path) &&
4690 !this.isModified(self.path)) return true;
4700 return self.checkRequired(v, this);
471 }
472
4730 if ('string' == typeof required) {
4740 message = required;
4750 required = undefined;
476 }
477
4780 var msg = message || errorMessages.general.required;
4790 this.validators.push([this.requiredValidator, msg, 'required']);
480
4810 return this;
482};
483
484/**
485 * Gets the default value
486 *
487 * @param {Object} scope the scope which callback are executed
488 * @param {Boolean} init
489 * @api private
490 */
491
4921SchemaType.prototype.getDefault = function (scope, init) {
4930 var ret = 'function' === typeof this.defaultValue
494 ? this.defaultValue.call(scope)
495 : this.defaultValue;
496
4970 if (null !== ret && undefined !== ret) {
4980 return this.cast(ret, scope, init);
499 } else {
5000 return ret;
501 }
502};
503
504/**
505 * Applies setters
506 *
507 * @param {Object} value
508 * @param {Object} scope
509 * @param {Boolean} init
510 * @api private
511 */
512
5131SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
5140 if (SchemaType._isRef(this, value, scope, init)) {
5150 return init
516 ? value
517 : this.cast(value, scope, init, priorVal);
518 }
519
5200 var v = value
521 , setters = this.setters
522 , len = setters.length
523
5240 if (!len) {
5250 if (null === v || undefined === v) return v;
5260 return this.cast(v, scope, init, priorVal)
527 }
528
5290 while (len--) {
5300 v = setters[len].call(scope, v, this);
531 }
532
5330 if (null === v || undefined === v) return v;
534
535 // do not cast until all setters are applied #665
5360 v = this.cast(v, scope, init, priorVal);
537
5380 return v;
539};
540
541/**
542 * Applies getters to a value
543 *
544 * @param {Object} value
545 * @param {Object} scope
546 * @api private
547 */
548
5491SchemaType.prototype.applyGetters = function (value, scope) {
5500 if (SchemaType._isRef(this, value, scope, true)) return value;
551
5520 var v = value
553 , getters = this.getters
554 , len = getters.length;
555
5560 if (!len) {
5570 return v;
558 }
559
5600 while (len--) {
5610 v = getters[len].call(scope, v, this);
562 }
563
5640 return v;
565};
566
567/**
568 * Sets default `select()` behavior for this path.
569 *
570 * Set to `true` if this path should always be included in the results, `false` if it should be excluded by default. This setting can be overridden at the query level.
571 *
572 * ####Example:
573 *
574 * T = db.model('T', new Schema({ x: { type: String, select: true }}));
575 * T.find(..); // field x will always be selected ..
576 * // .. unless overridden;
577 * T.find().select('-x').exec(callback);
578 *
579 * @param {Boolean} val
580 * @return {SchemaType} this
581 * @api public
582 */
583
5841SchemaType.prototype.select = function select (val) {
5850 this.selected = !! val;
5860 return this;
587}
588
589/**
590 * Performs a validation of `value` using the validators declared for this SchemaType.
591 *
592 * @param {any} value
593 * @param {Function} callback
594 * @param {Object} scope
595 * @api private
596 */
597
5981SchemaType.prototype.doValidate = function (value, fn, scope) {
5990 var err = false
600 , path = this.path
601 , count = this.validators.length;
602
6030 if (!count) return fn(null);
604
6050 function validate (ok, message, type, val) {
6060 if (err) return;
6070 if (ok === undefined || ok) {
6080 --count || fn(null);
609 } else {
6100 fn(err = new ValidatorError(path, message, type, val));
611 }
612 }
613
6140 this.validators.forEach(function (v) {
6150 var validator = v[0]
616 , message = v[1]
617 , type = v[2];
618
6190 if (validator instanceof RegExp) {
6200 validate(validator.test(value), message, type, value);
6210 } else if ('function' === typeof validator) {
6220 if (2 === validator.length) {
6230 validator.call(scope, value, function (ok) {
6240 validate(ok, message, type, value);
625 });
626 } else {
6270 validate(validator.call(scope, value), message, type, value);
628 }
629 }
630 });
631};
632
633/**
634 * Determines if value is a valid Reference.
635 *
636 * @param {SchemaType} self
637 * @param {Object} value
638 * @param {Document} doc
639 * @param {Boolean} init
640 * @return {Boolean}
641 * @api private
642 */
643
6441SchemaType._isRef = function (self, value, doc, init) {
645 // fast path
6460 var ref = init && self.options && self.options.ref;
647
6480 if (!ref && doc && doc.$__fullPath) {
649 // checks for
650 // - this populated with adhoc model and no ref was set in schema OR
651 // - setting / pushing values after population
6520 var path = doc.$__fullPath(self.path);
6530 var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
6540 ref = owner.populated(path);
655 }
656
6570 if (ref) {
6580 if (null == value) return true;
6590 if (!Buffer.isBuffer(value) && // buffers are objects too
660 'Binary' != value._bsontype // raw binary value from the db
661 && utils.isObject(value) // might have deselected _id in population query
662 ) {
6630 return true;
664 }
665 }
666
6670 return false;
668}
669
670/*!
671 * Module exports.
672 */
673
6741module.exports = exports = SchemaType;
675
6761exports.CastError = CastError;
677
6781exports.ValidatorError = ValidatorError;
679

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/statemachine.js

30%
49
15
34
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var utils = require('./utils');
7
8/*!
9 * StateMachine represents a minimal `interface` for the
10 * constructors it builds via StateMachine.ctor(...).
11 *
12 * @api private
13 */
14
151var StateMachine = module.exports = exports = function StateMachine () {
160 this.paths = {};
170 this.states = {};
18}
19
20/*!
21 * StateMachine.ctor('state1', 'state2', ...)
22 * A factory method for subclassing StateMachine.
23 * The arguments are a list of states. For each state,
24 * the constructor's prototype gets state transition
25 * methods named after each state. These transition methods
26 * place their path argument into the given state.
27 *
28 * @param {String} state
29 * @param {String} [state]
30 * @return {Function} subclass constructor
31 * @private
32 */
33
341StateMachine.ctor = function () {
351 var states = utils.args(arguments);
36
371 var ctor = function () {
380 StateMachine.apply(this, arguments);
390 this.stateNames = states;
40
410 var i = states.length
42 , state;
43
440 while (i--) {
450 state = states[i];
460 this.states[state] = {};
47 }
48 };
49
501 ctor.prototype.__proto__ = StateMachine.prototype;
51
521 states.forEach(function (state) {
53 // Changes the `path`'s state to `state`.
544 ctor.prototype[state] = function (path) {
550 this._changeState(path, state);
56 }
57 });
58
591 return ctor;
60};
61
62/*!
63 * This function is wrapped by the state change functions:
64 *
65 * - `require(path)`
66 * - `modify(path)`
67 * - `init(path)`
68 *
69 * @api private
70 */
71
721StateMachine.prototype._changeState = function _changeState (path, nextState) {
730 var prevBucket = this.states[this.paths[path]];
740 if (prevBucket) delete prevBucket[path];
75
760 this.paths[path] = nextState;
770 this.states[nextState][path] = true;
78}
79
80/*!
81 * ignore
82 */
83
841StateMachine.prototype.clear = function clear (state) {
850 var keys = Object.keys(this.states[state])
86 , i = keys.length
87 , path
88
890 while (i--) {
900 path = keys[i];
910 delete this.states[state][path];
920 delete this.paths[path];
93 }
94}
95
96/*!
97 * Checks to see if at least one path is in the states passed in via `arguments`
98 * e.g., this.some('required', 'inited')
99 *
100 * @param {String} state that we want to check for.
101 * @private
102 */
103
1041StateMachine.prototype.some = function some () {
1050 var self = this;
1060 var what = arguments.length ? arguments : this.stateNames;
1070 return Array.prototype.some.call(what, function (state) {
1080 return Object.keys(self.states[state]).length;
109 });
110}
111
112/*!
113 * This function builds the functions that get assigned to `forEach` and `map`,
114 * since both of those methods share a lot of the same logic.
115 *
116 * @param {String} iterMethod is either 'forEach' or 'map'
117 * @return {Function}
118 * @api private
119 */
120
1211StateMachine.prototype._iter = function _iter (iterMethod) {
1220 return function () {
1230 var numArgs = arguments.length
124 , states = utils.args(arguments, 0, numArgs-1)
125 , callback = arguments[numArgs-1];
126
1270 if (!states.length) states = this.stateNames;
128
1290 var self = this;
130
1310 var paths = states.reduce(function (paths, state) {
1320 return paths.concat(Object.keys(self.states[state]));
133 }, []);
134
1350 return paths[iterMethod](function (path, i, paths) {
1360 return callback(path, i, paths);
137 });
138 };
139}
140
141/*!
142 * Iterates over the paths that belong to one of the parameter states.
143 *
144 * The function profile can look like:
145 * this.forEach(state1, fn); // iterates over all paths in state1
146 * this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
147 * this.forEach(fn); // iterates over all paths in all states
148 *
149 * @param {String} [state]
150 * @param {String} [state]
151 * @param {Function} callback
152 * @private
153 */
154
1551StateMachine.prototype.forEach = function forEach () {
1560 this.forEach = this._iter('forEach');
1570 return this.forEach.apply(this, arguments);
158}
159
160/*!
161 * Maps over the paths that belong to one of the parameter states.
162 *
163 * The function profile can look like:
164 * this.forEach(state1, fn); // iterates over all paths in state1
165 * this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
166 * this.forEach(fn); // iterates over all paths in all states
167 *
168 * @param {String} [state]
169 * @param {String} [state]
170 * @param {Function} callback
171 * @return {Array}
172 * @private
173 */
174
1751StateMachine.prototype.map = function map () {
1760 this.map = this._iter('map');
1770 return this.map.apply(this, arguments);
178}
179
180

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/types/array.js

16%
192
31
161
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var EmbeddedDocument = require('./embedded');
71var Document = require('../document');
81var ObjectId = require('./objectid');
91var utils = require('../utils');
101var isMongooseObject = utils.isMongooseObject;
11
12/**
13 * Mongoose Array constructor.
14 *
15 * ####NOTE:
16 *
17 * _Values always have to be passed to the constructor to initialize, otherwise `MongooseArray#push` will mark the array as modified._
18 *
19 * @param {Array} values
20 * @param {String} path
21 * @param {Document} doc parent document
22 * @api private
23 * @inherits Array
24 * @see http://bit.ly/f6CnZU
25 */
26
271function MongooseArray (values, path, doc) {
280 var arr = [];
290 arr.push.apply(arr, values);
300 arr.__proto__ = MongooseArray.prototype;
31
320 arr._atomics = {};
330 arr.validators = [];
340 arr._path = path;
35
360 if (doc) {
370 arr._parent = doc;
380 arr._schema = doc.schema.path(path);
39 }
40
410 return arr;
42};
43
44/*!
45 * Inherit from Array
46 */
47
481MongooseArray.prototype = new Array;
49
50/**
51 * Stores a queue of atomic operations to perform
52 *
53 * @property _atomics
54 * @api private
55 */
56
571MongooseArray.prototype._atomics;
58
59/**
60 * Parent owner document
61 *
62 * @property _parent
63 * @api private
64 */
65
661MongooseArray.prototype._parent;
67
68/**
69 * Casts a member based on this arrays schema.
70 *
71 * @param {any} value
72 * @return value the casted value
73 * @api private
74 */
75
761MongooseArray.prototype._cast = function (value) {
770 var owner = this._owner;
780 var populated = false;
790 var Model;
80
810 if (this._parent) {
82 // if a populated array, we must cast to the same model
83 // instance as specified in the original query.
840 if (!owner) {
850 owner = this._owner = this._parent.ownerDocument
86 ? this._parent.ownerDocument()
87 : this._parent;
88 }
89
900 populated = owner.populated(this._path, true);
91 }
92
930 if (populated && null != value) {
94 // cast to the populated Models schema
950 var Model = populated.options.model;
96
97 // only objects are permitted so we can safely assume that
98 // non-objects are to be interpreted as _id
990 if (Buffer.isBuffer(value) ||
100 value instanceof ObjectId || !utils.isObject(value)) {
1010 value = { _id: value };
102 }
103
1040 value = new Model(value);
1050 return this._schema.caster.cast(value, this._parent, true)
106 }
107
1080 return this._schema.caster.cast(value, this._parent, false)
109}
110
111/**
112 * Marks this array as modified.
113 *
114 * If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)
115 *
116 * @param {EmbeddedDocument} embeddedDoc the embedded doc that invoked this method on the Array
117 * @param {String} embeddedPath the path which changed in the embeddedDoc
118 * @api private
119 */
120
1211MongooseArray.prototype._markModified = function (elem, embeddedPath) {
1220 var parent = this._parent
123 , dirtyPath;
124
1250 if (parent) {
1260 dirtyPath = this._path;
127
1280 if (arguments.length) {
1290 if (null != embeddedPath) {
130 // an embedded doc bubbled up the change
1310 dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
132 } else {
133 // directly set an index
1340 dirtyPath = dirtyPath + '.' + elem;
135 }
136 }
1370 parent.markModified(dirtyPath);
138 }
139
1400 return this;
141};
142
143/**
144 * Register an atomic operation with the parent.
145 *
146 * @param {Array} op operation
147 * @param {any} val
148 * @api private
149 */
150
1511MongooseArray.prototype._registerAtomic = function (op, val) {
1520 if ('$set' == op) {
153 // $set takes precedence over all other ops.
154 // mark entire array modified.
1550 this._atomics = { $set: val };
1560 return this;
157 }
158
1590 var atomics = this._atomics;
160
161 // reset pop/shift after save
1620 if ('$pop' == op && !('$pop' in atomics)) {
1630 var self = this;
1640 this._parent.once('save', function () {
1650 self._popped = self._shifted = null;
166 });
167 }
168
169 // check for impossible $atomic combos (Mongo denies more than one
170 // $atomic op on a single path
1710 if (this._atomics.$set ||
172 Object.keys(atomics).length && !(op in atomics)) {
173 // a different op was previously registered.
174 // save the entire thing.
1750 this._atomics = { $set: this };
1760 return this;
177 }
178
1790 if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
1800 atomics[op] || (atomics[op] = []);
1810 atomics[op] = atomics[op].concat(val);
1820 } else if (op === '$pullDocs') {
1830 var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
184 , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
1850 selector['$in'] = selector['$in'].concat(val);
186 } else {
1870 atomics[op] = val;
188 }
189
1900 return this;
191};
192
193/**
194 * Depopulates stored atomic operation values as necessary for direct insertion to MongoDB.
195 *
196 * If no atomics exist, we return all array values after conversion.
197 *
198 * @return {Array}
199 * @method $__getAtomics
200 * @memberOf MongooseArray
201 * @api private
202 */
203
2041MongooseArray.prototype.$__getAtomics = function () {
2050 var ret = [];
2060 var keys = Object.keys(this._atomics);
2070 var i = keys.length;
208
2090 if (0 === i) {
2100 ret[0] = ['$set', this.toObject({ depopulate: 1 })];
2110 return ret;
212 }
213
2140 while (i--) {
2150 var op = keys[i];
2160 var val = this._atomics[op];
217
218 // the atomic values which are arrays are not MongooseArrays. we
219 // need to convert their elements as if they were MongooseArrays
220 // to handle populated arrays versus DocumentArrays properly.
2210 if (isMongooseObject(val)) {
2220 val = val.toObject({ depopulate: 1 });
2230 } else if (Array.isArray(val)) {
2240 val = this.toObject.call(val, { depopulate: 1 });
2250 } else if (val.valueOf) {
2260 val = val.valueOf();
227 }
228
2290 if ('$addToSet' == op) {
2300 val = { $each: val }
231 }
232
2330 ret.push([op, val]);
234 }
235
2360 return ret;
237}
238
239/**
240 * Returns the number of pending atomic operations to send to the db for this array.
241 *
242 * @api private
243 * @return {Number}
244 */
245
2461MongooseArray.prototype.hasAtomics = function hasAtomics () {
2470 if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
2480 return 0;
249 }
250
2510 return Object.keys(this._atomics).length;
252}
253
254/**
255 * Wraps [`Array#push`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push) with proper change tracking.
256 *
257 * @param {Object} [args...]
258 * @api public
259 */
260
2611MongooseArray.prototype.push = function () {
2620 var values = [].map.call(arguments, this._cast, this)
263 , ret = [].push.apply(this, values);
264
265 // $pushAll might be fibbed (could be $push). But it makes it easier to
266 // handle what could have been $push, $pushAll combos
2670 this._registerAtomic('$pushAll', values);
2680 this._markModified();
2690 return ret;
270};
271
272/**
273 * Pushes items to the array non-atomically.
274 *
275 * ####NOTE:
276 *
277 * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
278 *
279 * @param {any} [args...]
280 * @api public
281 */
282
2831MongooseArray.prototype.nonAtomicPush = function () {
2840 var values = [].map.call(arguments, this._cast, this)
285 , ret = [].push.apply(this, values);
2860 this._registerAtomic('$set', this);
2870 this._markModified();
2880 return ret;
289};
290
291/**
292 * Pops the array atomically at most one time per document `save()`.
293 *
294 * #### NOTE:
295 *
296 * _Calling this mulitple times on an array before saving sends the same command as calling it once._
297 * _This update is implemented using the MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop) method which enforces this restriction._
298 *
299 * doc.array = [1,2,3];
300 *
301 * var popped = doc.array.$pop();
302 * console.log(popped); // 3
303 * console.log(doc.array); // [1,2]
304 *
305 * // no affect
306 * popped = doc.array.$pop();
307 * console.log(doc.array); // [1,2]
308 *
309 * doc.save(function (err) {
310 * if (err) return handleError(err);
311 *
312 * // we saved, now $pop works again
313 * popped = doc.array.$pop();
314 * console.log(popped); // 2
315 * console.log(doc.array); // [1]
316 * })
317 *
318 * @api public
319 * @method $pop
320 * @memberOf MongooseArray
321 * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop
322 */
323
3241MongooseArray.prototype.$pop = function () {
3250 this._registerAtomic('$pop', 1);
3260 this._markModified();
327
328 // only allow popping once
3290 if (this._popped) return;
3300 this._popped = true;
331
3320 return [].pop.call(this);
333};
334
335/**
336 * Wraps [`Array#pop`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/pop) with proper change tracking.
337 *
338 * ####Note:
339 *
340 * _marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it._
341 *
342 * @see MongooseArray#$pop #types_array_MongooseArray-%24pop
343 * @api public
344 */
345
3461MongooseArray.prototype.pop = function () {
3470 var ret = [].pop.call(this);
3480 this._registerAtomic('$set', this);
3490 this._markModified();
3500 return ret;
351};
352
353/**
354 * Atomically shifts the array at most one time per document `save()`.
355 *
356 * ####NOTE:
357 *
358 * _Calling this mulitple times on an array before saving sends the same command as calling it once._
359 * _This update is implemented using the MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop) method which enforces this restriction._
360 *
361 * doc.array = [1,2,3];
362 *
363 * var shifted = doc.array.$shift();
364 * console.log(shifted); // 1
365 * console.log(doc.array); // [2,3]
366 *
367 * // no affect
368 * shifted = doc.array.$shift();
369 * console.log(doc.array); // [2,3]
370 *
371 * doc.save(function (err) {
372 * if (err) return handleError(err);
373 *
374 * // we saved, now $shift works again
375 * shifted = doc.array.$shift();
376 * console.log(shifted ); // 2
377 * console.log(doc.array); // [3]
378 * })
379 *
380 * @api public
381 * @memberOf MongooseArray
382 * @method $shift
383 * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop
384 */
385
3861MongooseArray.prototype.$shift = function $shift () {
3870 this._registerAtomic('$pop', -1);
3880 this._markModified();
389
390 // only allow shifting once
3910 if (this._shifted) return;
3920 this._shifted = true;
393
3940 return [].shift.call(this);
395};
396
397/**
398 * Wraps [`Array#shift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
399 *
400 * ####Example:
401 *
402 * doc.array = [2,3];
403 * var res = doc.array.shift();
404 * console.log(res) // 2
405 * console.log(doc.array) // [3]
406 *
407 * ####Note:
408 *
409 * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
410 *
411 * @api public
412 */
413
4141MongooseArray.prototype.shift = function () {
4150 var ret = [].shift.call(this);
4160 this._registerAtomic('$set', this);
4170 this._markModified();
4180 return ret;
419};
420
421/**
422 * Pulls items from the array atomically.
423 *
424 * ####Examples:
425 *
426 * doc.array.pull(ObjectId)
427 * doc.array.pull({ _id: 'someId' })
428 * doc.array.pull(36)
429 * doc.array.pull('tag 1', 'tag 2')
430 *
431 * To remove a document from a subdocument array we may pass an object with a matching `_id`.
432 *
433 * doc.subdocs.push({ _id: 4815162342 })
434 * doc.subdocs.pull({ _id: 4815162342 }) // removed
435 *
436 * Or we may passing the _id directly and let mongoose take care of it.
437 *
438 * doc.subdocs.push({ _id: 4815162342 })
439 * doc.subdocs.pull(4815162342); // works
440 *
441 * @param {any} [args...]
442 * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull
443 * @api public
444 */
445
4461MongooseArray.prototype.pull = function () {
4470 var values = [].map.call(arguments, this._cast, this)
448 , cur = this._parent.get(this._path)
449 , i = cur.length
450 , mem;
451
4520 while (i--) {
4530 mem = cur[i];
4540 if (mem instanceof EmbeddedDocument) {
4550 if (values.some(function (v) { return v.equals(mem); } )) {
4560 [].splice.call(cur, i, 1);
457 }
4580 } else if (~cur.indexOf.call(values, mem)) {
4590 [].splice.call(cur, i, 1);
460 }
461 }
462
4630 if (values[0] instanceof EmbeddedDocument) {
4640 this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
465 } else {
4660 this._registerAtomic('$pullAll', values);
467 }
468
4690 this._markModified();
4700 return this;
471};
472
473/**
474 * Alias of [pull](#types_array_MongooseArray-pull)
475 *
476 * @see MongooseArray#pull #types_array_MongooseArray-pull
477 * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull
478 * @api public
479 * @memberOf MongooseArray
480 * @method remove
481 */
482
4831MongooseArray.prototype.remove = MongooseArray.prototype.pull;
484
485/**
486 * Wraps [`Array#splice`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice) with proper change tracking and casting.
487 *
488 * ####Note:
489 *
490 * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
491 *
492 * @api public
493 */
494
4951MongooseArray.prototype.splice = function splice () {
4960 var ret, vals, i;
497
4980 if (arguments.length) {
4990 vals = [];
5000 for (i = 0; i < arguments.length; ++i) {
5010 vals[i] = i < 2
502 ? arguments[i]
503 : this._cast(arguments[i]);
504 }
5050 ret = [].splice.apply(this, vals);
5060 this._registerAtomic('$set', this);
5070 this._markModified();
508 }
509
5100 return ret;
511}
512
513/**
514 * Wraps [`Array#unshift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
515 *
516 * ####Note:
517 *
518 * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
519 *
520 * @api public
521 */
522
5231MongooseArray.prototype.unshift = function () {
5240 var values = [].map.call(arguments, this._cast, this);
5250 [].unshift.apply(this, values);
5260 this._registerAtomic('$set', this);
5270 this._markModified();
5280 return this.length;
529};
530
531/**
532 * Wraps [`Array#sort`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort) with proper change tracking.
533 *
534 * ####NOTE:
535 *
536 * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
537 *
538 * @api public
539 */
540
5411MongooseArray.prototype.sort = function () {
5420 var ret = [].sort.apply(this, arguments);
5430 this._registerAtomic('$set', this);
5440 this._markModified();
5450 return ret;
546}
547
548/**
549 * Adds values to the array if not already present.
550 *
551 * ####Example:
552 *
553 * console.log(doc.array) // [2,3,4]
554 * var added = doc.array.addToSet(4,5);
555 * console.log(doc.array) // [2,3,4,5]
556 * console.log(added) // [5]
557 *
558 * @param {any} [args...]
559 * @return {Array} the values that were added
560 * @api public
561 */
562
5631MongooseArray.prototype.addToSet = function addToSet () {
5640 var values = [].map.call(arguments, this._cast, this)
565 , added = []
566 , type = values[0] instanceof EmbeddedDocument ? 'doc' :
567 values[0] instanceof Date ? 'date' :
568 '';
569
5700 values.forEach(function (v) {
5710 var found;
5720 switch (type) {
573 case 'doc':
5740 found = this.some(function(doc){ return doc.equals(v) });
5750 break;
576 case 'date':
5770 var val = +v;
5780 found = this.some(function(d){ return +d === val });
5790 break;
580 default:
5810 found = ~this.indexOf(v);
582 }
583
5840 if (!found) {
5850 [].push.call(this, v);
5860 this._registerAtomic('$addToSet', v);
5870 this._markModified();
5880 [].push.call(added, v);
589 }
590 }, this);
591
5920 return added;
593};
594
595/**
596 * Sets the casted `val` at index `i` and marks the array modified.
597 *
598 * ####Example:
599 *
600 * // given documents based on the following
601 * var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
602 *
603 * var doc = new Doc({ array: [2,3,4] })
604 *
605 * console.log(doc.array) // [2,3,4]
606 *
607 * doc.array.set(1,"5");
608 * console.log(doc.array); // [2,5,4] // properly cast to number
609 * doc.save() // the change is saved
610 *
611 * // VS not using array#set
612 * doc.array[1] = "5";
613 * console.log(doc.array); // [2,"5",4] // no casting
614 * doc.save() // change is not saved
615 *
616 * @return {Array} this
617 * @api public
618 */
619
6201MongooseArray.prototype.set = function set (i, val) {
6210 this[i] = this._cast(val);
6220 this._markModified(i);
6230 return this;
624}
625
626/**
627 * Returns a native js Array.
628 *
629 * @param {Object} options
630 * @return {Array}
631 * @api public
632 */
633
6341MongooseArray.prototype.toObject = function (options) {
6350 if (options && options.depopulate) {
6360 return this.map(function (doc) {
6370 return doc instanceof Document
638 ? doc.toObject(options)
639 : doc
640 });
641 }
642
6430 return this.slice();
644}
645
646/**
647 * Helper for console.log
648 *
649 * @api public
650 */
651
6521MongooseArray.prototype.inspect = function () {
6530 return '[' + this.map(function (doc) {
6540 return ' ' + doc;
655 }) + ' ]';
656};
657
658/**
659 * Return the index of `obj` or `-1` if not found.
660 *
661 * @param {Object} obj the item to look for
662 * @return {Number}
663 * @api public
664 */
665
6661MongooseArray.prototype.indexOf = function indexOf (obj) {
6670 if (obj instanceof ObjectId) obj = obj.toString();
6680 for (var i = 0, len = this.length; i < len; ++i) {
6690 if (obj == this[i])
6700 return i;
671 }
6720 return -1;
673};
674
675/*!
676 * Module exports.
677 */
678
6791module.exports = exports = MongooseArray;
680

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/types/buffer.js

27%
62
17
45
LineHitsSource
1
2/*!
3 * Access driver.
4 */
5
61var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';
7
8/*!
9 * Module dependencies.
10 */
11
121var Binary = require(driver + '/binary');
13
14/**
15 * Mongoose Buffer constructor.
16 *
17 * Values always have to be passed to the constructor to initialize.
18 *
19 * @param {Buffer} value
20 * @param {String} encode
21 * @param {Number} offset
22 * @api private
23 * @inherits Buffer
24 * @see http://bit.ly/f6CnZU
25 */
26
271function MongooseBuffer (value, encode, offset) {
280 var length = arguments.length;
290 var val;
30
310 if (0 === length || null === arguments[0] || undefined === arguments[0]) {
320 val = 0;
33 } else {
340 val = value;
35 }
36
370 var encoding;
380 var path;
390 var doc;
40
410 if (Array.isArray(encode)) {
42 // internal casting
430 path = encode[0];
440 doc = encode[1];
45 } else {
460 encoding = encode;
47 }
48
490 var buf = new Buffer(val, encoding, offset);
500 buf.__proto__ = MongooseBuffer.prototype;
51
52 // make sure these internal props don't show up in Object.keys()
530 Object.defineProperties(buf, {
54 validators: { value: [] }
55 , _path: { value: path }
56 , _parent: { value: doc }
57 });
58
590 if (doc && "string" === typeof path) {
600 Object.defineProperty(buf, '_schema', {
61 value: doc.schema.path(path)
62 });
63 }
64
650 buf._subtype = 0;
660 return buf;
67};
68
69/*!
70 * Inherit from Buffer.
71 */
72
731MongooseBuffer.prototype = new Buffer(0);
74
75/**
76 * Parent owner document
77 *
78 * @api private
79 * @property _parent
80 */
81
821MongooseBuffer.prototype._parent;
83
84/**
85 * Default subtype for the Binary representing this Buffer
86 *
87 * @api private
88 * @property _subtype
89 */
90
911MongooseBuffer.prototype._subtype;
92
93/**
94 * Marks this buffer as modified.
95 *
96 * @api private
97 */
98
991MongooseBuffer.prototype._markModified = function () {
1000 var parent = this._parent;
101
1020 if (parent) {
1030 parent.markModified(this._path);
104 }
1050 return this;
106};
107
108/**
109* Writes the buffer.
110*/
111
1121MongooseBuffer.prototype.write = function () {
1130 var written = Buffer.prototype.write.apply(this, arguments);
114
1150 if (written > 0) {
1160 this._markModified();
117 }
118
1190 return written;
120};
121
122/**
123 * Copies the buffer.
124 *
125 * ####Note:
126 *
127 * `Buffer#copy` does not mark `target` as modified so you must copy from a `MongooseBuffer` for it to work as expected. This is a work around since `copy` modifies the target, not this.
128 *
129 * @return {MongooseBuffer}
130 * @param {Buffer} target
131 */
132
1331MongooseBuffer.prototype.copy = function (target) {
1340 var ret = Buffer.prototype.copy.apply(this, arguments);
135
1360 if (target instanceof MongooseBuffer) {
1370 target._markModified();
138 }
139
1400 return ret;
141};
142
143/*!
144 * Compile other Buffer methods marking this buffer as modified.
145 */
146
1471;(
148// node < 0.5
149'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +
150'writeFloat writeDouble fill ' +
151'utf8Write binaryWrite asciiWrite set ' +
152
153// node >= 0.5
154'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +
155'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +
156'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'
157).split(' ').forEach(function (method) {
15831 if (!Buffer.prototype[method]) return;
15919 MongooseBuffer.prototype[method] = new Function(
160 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +
161 'this._markModified();' +
162 'return ret;'
163 )
164});
165
166/**
167 * Converts this buffer to its Binary type representation.
168 *
169 * ####SubTypes:
170 *
171 * var bson = require('bson')
172 * bson.BSON_BINARY_SUBTYPE_DEFAULT
173 * bson.BSON_BINARY_SUBTYPE_FUNCTION
174 * bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
175 * bson.BSON_BINARY_SUBTYPE_UUID
176 * bson.BSON_BINARY_SUBTYPE_MD5
177 * bson.BSON_BINARY_SUBTYPE_USER_DEFINED
178 *
179 * doc.buffer.toObject(bson.BSON_BINARY_SUBTYPE_USER_DEFINED);
180 *
181 * @see http://bsonspec.org/#/specification
182 * @param {Hex} [subtype]
183 * @return {Binary}
184 * @api public
185 */
186
1871MongooseBuffer.prototype.toObject = function (options) {
1880 var subtype = 'number' == typeof options
189 ? options
190 : (this._subtype || 0);
1910 return new Binary(this, subtype);
192};
193
194/**
195 * Determines if this buffer is equals to `other` buffer
196 *
197 * @param {Buffer} other
198 * @return {Boolean}
199 */
200
2011MongooseBuffer.prototype.equals = function (other) {
2020 if (!Buffer.isBuffer(other)) {
2030 return false;
204 }
205
2060 if (this.length !== other.length) {
2070 return false;
208 }
209
2100 for (var i = 0; i < this.length; ++i) {
2110 if (this[i] !== other[i]) return false;
212 }
213
2140 return true;
215}
216
217/**
218 * Sets the subtype option and marks the buffer modified.
219 *
220 * ####SubTypes:
221 *
222 * var bson = require('bson')
223 * bson.BSON_BINARY_SUBTYPE_DEFAULT
224 * bson.BSON_BINARY_SUBTYPE_FUNCTION
225 * bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
226 * bson.BSON_BINARY_SUBTYPE_UUID
227 * bson.BSON_BINARY_SUBTYPE_MD5
228 * bson.BSON_BINARY_SUBTYPE_USER_DEFINED
229 *
230 * doc.buffer.subtype(bson.BSON_BINARY_SUBTYPE_UUID);
231 *
232 * @see http://bsonspec.org/#/specification
233 * @param {Hex} subtype
234 * @api public
235 */
236
2371MongooseBuffer.prototype.subtype = function (subtype) {
2380 if ('number' != typeof subtype) {
2390 throw new TypeError('Invalid subtype. Expected a number');
240 }
241
2420 if (this._subtype != subtype) {
2430 this._markModified();
244 }
245
2460 this._subtype = subtype;
247}
248
249/*!
250 * Module exports.
251 */
252
2531MongooseBuffer.Binary = Binary;
254
2551module.exports = MongooseBuffer;
256

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/types/documentarray.js

16%
59
10
49
LineHitsSource
1
2/*!
3 * Module dependencies.
4 */
5
61var MongooseArray = require('./array')
7 , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'
8 , ObjectId = require(driver + '/objectid')
9 , ObjectIdSchema = require('../schema/objectid')
10 , utils = require('../utils')
11 , util = require('util')
12 , Document = require('../document')
13
14/**
15 * DocumentArray constructor
16 *
17 * @param {Array} values
18 * @param {String} path the path to this array
19 * @param {Document} doc parent document
20 * @api private
21 * @return {MongooseDocumentArray}
22 * @inherits MongooseArray
23 * @see http://bit.ly/f6CnZU
24 */
25
261function MongooseDocumentArray (values, path, doc) {
270 var arr = [];
28
29 // Values always have to be passed to the constructor to initialize, since
30 // otherwise MongooseArray#push will mark the array as modified to the parent.
310 arr.push.apply(arr, values);
320 arr.__proto__ = MongooseDocumentArray.prototype;
33
340 arr._atomics = {};
350 arr.validators = [];
360 arr._path = path;
37
380 if (doc) {
390 arr._parent = doc;
400 arr._schema = doc.schema.path(path);
410 doc.on('save', arr.notify('save'));
420 doc.on('isNew', arr.notify('isNew'));
43 }
44
450 return arr;
46};
47
48/*!
49 * Inherits from MongooseArray
50 */
51
521MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;
53
54/**
55 * Overrides MongooseArray#cast
56 *
57 * @api private
58 */
59
601MongooseDocumentArray.prototype._cast = function (value) {
610 if (value instanceof this._schema.casterConstructor) {
620 if (!(value.__parent && value.__parentArray)) {
63 // value may have been created using array.create()
640 value.__parent = this._parent;
650 value.__parentArray = this;
66 }
670 return value;
68 }
69
70 // handle cast('string') or cast(ObjectId) etc.
71 // only objects are permitted so we can safely assume that
72 // non-objects are to be interpreted as _id
730 if (Buffer.isBuffer(value) ||
74 value instanceof ObjectId || !utils.isObject(value)) {
750 value = { _id: value };
76 }
77
780 return new this._schema.casterConstructor(value, this);
79};
80
81/**
82 * Searches array items for the first document with a matching _id.
83 *
84 * ####Example:
85 *
86 * var embeddedDoc = m.array.id(some_id);
87 *
88 * @return {EmbeddedDocument|null} the subdocuent or null if not found.
89 * @param {ObjectId|String|Number|Buffer} id
90 * @TODO cast to the _id based on schema for proper comparison
91 * @api public
92 */
93
941MongooseDocumentArray.prototype.id = function (id) {
950 var casted
96 , sid
97 , _id
98
990 try {
1000 var casted_ = ObjectIdSchema.prototype.cast.call({}, id);
1010 if (casted_) casted = String(casted_);
102 } catch (e) {
1030 casted = null;
104 }
105
1060 for (var i = 0, l = this.length; i < l; i++) {
1070 _id = this[i].get('_id');
108
1090 if (_id instanceof Document) {
1100 sid || (sid = String(id));
1110 if (sid == _id._id) return this[i];
1120 } else if (!(_id instanceof ObjectId)) {
1130 sid || (sid = String(id));
1140 if (sid == _id) return this[i];
1150 } else if (casted == _id) {
1160 return this[i];
117 }
118 }
119
1200 return null;
121};
122
123/**
124 * Returns a native js Array of plain js objects
125 *
126 * ####NOTE:
127 *
128 * _Each sub-document is converted to a plain object by calling its `#toObject` method._
129 *
130 * @param {Object} [options] optional options to pass to each documents `toObject` method call during conversion
131 * @return {Array}
132 * @api public
133 */
134
1351MongooseDocumentArray.prototype.toObject = function (options) {
1360 return this.map(function (doc) {
1370 return doc && doc.toObject(options) || null;
138 });
139};
140
141/**
142 * Helper for console.log
143 *
144 * @api public
145 */
146
1471MongooseDocumentArray.prototype.inspect = function () {
1480 return '[' + this.map(function (doc) {
1490 if (doc) {
1500 return doc.inspect
151 ? doc.inspect()
152 : util.inspect(doc)
153 }
1540 return 'null'
155 }).join('\n') + ']';
156};
157
158/**
159 * Creates a subdocument casted to this schema.
160 *
161 * This is the same subdocument constructor used for casting.
162 *
163 * @param {Object} obj the value to cast to this arrays SubDocument schema
164 * @api public
165 */
166
1671MongooseDocumentArray.prototype.create = function (obj) {
1680 return new this._schema.casterConstructor(obj);
169}
170
171/**
172 * Creates a fn that notifies all child docs of `event`.
173 *
174 * @param {String} event
175 * @return {Function}
176 * @api private
177 */
178
1791MongooseDocumentArray.prototype.notify = function notify (event) {
1800 var self = this;
1810 return function notify (val) {
1820 var i = self.length;
1830 while (i--) {
1840 if (!self[i]) continue;
1850 self[i].emit(event, val);
186 }
187 }
188}
189
190/*!
191 * Module exports.
192 */
193
1941module.exports = MongooseDocumentArray;
195

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/types/embedded.js

17%
86
15
71
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var Document = require('../document')
6 , inspect = require('util').inspect;
7
8/**
9 * EmbeddedDocument constructor.
10 *
11 * @param {Object} obj js object returned from the db
12 * @param {MongooseDocumentArray} parentArr the parent array of this document
13 * @param {Boolean} skipId
14 * @inherits Document
15 * @api private
16 */
17
181function EmbeddedDocument (obj, parentArr, skipId, fields) {
190 if (parentArr) {
200 this.__parentArray = parentArr;
210 this.__parent = parentArr._parent;
22 } else {
230 this.__parentArray = undefined;
240 this.__parent = undefined;
25 }
26
270 Document.call(this, obj, fields, skipId);
28
290 var self = this;
300 this.on('isNew', function (val) {
310 self.isNew = val;
32 });
33};
34
35/*!
36 * Inherit from Document
37 */
38
391EmbeddedDocument.prototype.__proto__ = Document.prototype;
40
41/**
42 * Marks the embedded doc modified.
43 *
44 * ####Example:
45 *
46 * var doc = blogpost.comments.id(hexstring);
47 * doc.mixed.type = 'changed';
48 * doc.markModified('mixed.type');
49 *
50 * @param {String} path the path which changed
51 * @api public
52 */
53
541EmbeddedDocument.prototype.markModified = function (path) {
550 if (!this.__parentArray) return;
56
570 this.$__.activePaths.modify(path);
58
590 if (this.isNew) {
60 // Mark the WHOLE parent array as modified
61 // if this is a new document (i.e., we are initializing
62 // a document),
630 this.__parentArray._markModified();
64 } else
650 this.__parentArray._markModified(this, path);
66};
67
68/**
69 * Used as a stub for [hooks.js](https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3)
70 *
71 * ####NOTE:
72 *
73 * _This is a no-op. Does not actually save the doc to the db._
74 *
75 * @param {Function} [fn]
76 * @return {EmbeddedDocument} this
77 * @api private
78 */
79
801EmbeddedDocument.prototype.save = function(fn) {
810 if (fn)
820 fn(null);
830 return this;
84};
85
86/**
87 * Removes the subdocument from its parent array.
88 *
89 * @param {Function} [fn]
90 * @api public
91 */
92
931EmbeddedDocument.prototype.remove = function (fn) {
940 if (!this.__parentArray) return this;
95
960 var _id;
970 if (!this.willRemove) {
980 _id = this._doc._id;
990 if (!_id) {
1000 throw new Error('For your own good, Mongoose does not know ' +
101 'how to remove an EmbeddedDocument that has no _id');
102 }
1030 this.__parentArray.pull({ _id: _id });
1040 this.willRemove = true;
1050 registerRemoveListener(this);
106 }
107
1080 if (fn)
1090 fn(null);
110
1110 return this;
112};
113
114/*!
115 * Registers remove event listeners for triggering
116 * on subdocuments.
117 *
118 * @param {EmbeddedDocument} sub
119 * @api private
120 */
121
1221function registerRemoveListener (sub) {
1230 var owner = sub.ownerDocument();
124
1250 owner.on('save', emitRemove);
1260 owner.on('remove', emitRemove);
127
1280 function emitRemove () {
1290 owner.removeListener('save', emitRemove);
1300 owner.removeListener('remove', emitRemove);
1310 sub.emit('remove', sub);
1320 owner = sub = emitRemove = null;
133 };
134};
135
136/**
137 * Override #update method of parent documents.
138 * @api private
139 */
140
1411EmbeddedDocument.prototype.update = function () {
1420 throw new Error('The #update method is not available on EmbeddedDocuments');
143}
144
145/**
146 * Helper for console.log
147 *
148 * @api public
149 */
150
1511EmbeddedDocument.prototype.inspect = function () {
1520 return inspect(this.toObject());
153};
154
155/**
156 * Marks a path as invalid, causing validation to fail.
157 *
158 * @param {String} path the field to invalidate
159 * @param {String|Error} err error which states the reason `path` was invalid
160 * @return {Boolean}
161 * @api public
162 */
163
1641EmbeddedDocument.prototype.invalidate = function (path, err, val, first) {
1650 if (!this.__parent) {
1660 var msg = 'Unable to invalidate a subdocument that has not been added to an array.'
1670 throw new Error(msg);
168 }
169
1700 var index = this.__parentArray.indexOf(this);
1710 var parentPath = this.__parentArray._path;
1720 var fullPath = [parentPath, index, path].join('.');
173
174 // sniffing arguments:
175 // need to check if user passed a value to keep
176 // our error message clean.
1770 if (2 < arguments.length) {
1780 this.__parent.invalidate(fullPath, err, val);
179 } else {
1800 this.__parent.invalidate(fullPath, err);
181 }
182
1830 if (first)
1840 this.$__.validationError = this.ownerDocument().$__.validationError;
1850 return true;
186}
187
188/**
189 * Returns the top level document of this sub-document.
190 *
191 * @return {Document}
192 */
193
1941EmbeddedDocument.prototype.ownerDocument = function () {
1950 if (this.$__.ownerDocument) {
1960 return this.$__.ownerDocument;
197 }
198
1990 var parent = this.__parent;
2000 if (!parent) return this;
201
2020 while (parent.__parent) {
2030 parent = parent.__parent;
204 }
205
2060 return this.$__.ownerDocument = parent;
207}
208
209/**
210 * Returns the full path to this document. If optional `path` is passed, it is appended to the full path.
211 *
212 * @param {String} [path]
213 * @return {String}
214 * @api private
215 * @method $__fullPath
216 * @memberOf EmbeddedDocument
217 */
218
2191EmbeddedDocument.prototype.$__fullPath = function (path) {
2200 if (!this.$__.fullPath) {
2210 var parent = this;
2220 if (!parent.__parent) return path;
223
2240 var paths = [];
2250 while (parent.__parent) {
2260 paths.unshift(parent.__parentArray._path);
2270 parent = parent.__parent;
228 }
229
2300 this.$__.fullPath = paths.join('.');
231
2320 if (!this.$__.ownerDocument) {
233 // optimization
2340 this.$__.ownerDocument = parent;
235 }
236 }
237
2380 return path
239 ? this.$__.fullPath + '.' + path
240 : this.$__.fullPath;
241}
242
243/**
244 * Returns this sub-documents parent document.
245 *
246 * @api public
247 */
248
2491EmbeddedDocument.prototype.parent = function () {
2500 return this.__parent;
251}
252
253/**
254 * Returns this sub-documents parent array.
255 *
256 * @api public
257 */
258
2591EmbeddedDocument.prototype.parentArray = function () {
2600 return this.__parentArray;
261}
262
263/*!
264 * Module exports.
265 */
266
2671module.exports = EmbeddedDocument;
268

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/types/index.js

100%
5
5
0
LineHitsSource
1
2/*!
3 * Module exports.
4 */
5
61exports.Array = require('./array');
71exports.Buffer = require('./buffer');
8
91exports.Document = // @deprecate
10exports.Embedded = require('./embedded');
11
121exports.DocumentArray = require('./documentarray');
131exports.ObjectId = require('./objectid');
14

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/types/objectid.js

100%
3
3
0
LineHitsSource
1
2/*!
3 * Access driver.
4 */
5
61var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';
7
8/**
9 * ObjectId type constructor
10 *
11 * ####Example
12 *
13 * var id = new mongoose.Types.ObjectId;
14 *
15 * @constructor ObjectId
16 */
17
181var ObjectId = require(driver + '/objectid');
191module.exports = ObjectId;
20
21

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/utils.js

27%
221
61
160
LineHitsSource
1/*!
2 * Module dependencies.
3 */
4
51var ReadPref = require('mongodb').ReadPreference
6 , ObjectId = require('./types/objectid')
7 , cloneRegExp = require('regexp-clone')
8 , sliced = require('sliced')
9 , mpath = require('mpath')
10 , ms = require('ms')
11 , MongooseBuffer
12 , MongooseArray
13 , Document
14
15/*!
16 * Produces a collection name from model `name`.
17 *
18 * @param {String} name a model name
19 * @return {String} a collection name
20 * @api private
21 */
22
231exports.toCollectionName = function (name, options) {
240 options = options || {};
250 if ('system.profile' === name) return name;
260 if ('system.indexes' === name) return name;
270 if (options.pluralization === false) return name;
280 return pluralize(name.toLowerCase());
29};
30
31/**
32 * Pluralization rules.
33 *
34 * These rules are applied while processing the argument to `toCollectionName`.
35 *
36 * @deprecated remove in 4.x gh-1350
37 */
38
391exports.pluralization = [
40 [/(m)an$/gi, '$1en'],
41 [/(pe)rson$/gi, '$1ople'],
42 [/(child)$/gi, '$1ren'],
43 [/^(ox)$/gi, '$1en'],
44 [/(ax|test)is$/gi, '$1es'],
45 [/(octop|vir)us$/gi, '$1i'],
46 [/(alias|status)$/gi, '$1es'],
47 [/(bu)s$/gi, '$1ses'],
48 [/(buffal|tomat|potat)o$/gi, '$1oes'],
49 [/([ti])um$/gi, '$1a'],
50 [/sis$/gi, 'ses'],
51 [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
52 [/(hive)$/gi, '$1s'],
53 [/([^aeiouy]|qu)y$/gi, '$1ies'],
54 [/(x|ch|ss|sh)$/gi, '$1es'],
55 [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
56 [/([m|l])ouse$/gi, '$1ice'],
57 [/(quiz)$/gi, '$1zes'],
58 [/s$/gi, 's'],
59 [/([^a-z])$/, '$1'],
60 [/$/gi, 's']
61];
621var rules = exports.pluralization;
63
64/**
65 * Uncountable words.
66 *
67 * These words are applied while processing the argument to `toCollectionName`.
68 * @api public
69 */
70
711exports.uncountables = [
72 'advice',
73 'energy',
74 'excretion',
75 'digestion',
76 'cooperation',
77 'health',
78 'justice',
79 'labour',
80 'machinery',
81 'equipment',
82 'information',
83 'pollution',
84 'sewage',
85 'paper',
86 'money',
87 'species',
88 'series',
89 'rain',
90 'rice',
91 'fish',
92 'sheep',
93 'moose',
94 'deer',
95 'news',
96 'expertise',
97 'status',
98 'media'
99];
1001var uncountables = exports.uncountables;
101
102/*!
103 * Pluralize function.
104 *
105 * @author TJ Holowaychuk (extracted from _ext.js_)
106 * @param {String} string to pluralize
107 * @api private
108 */
109
1101function pluralize (str) {
1110 var rule, found;
1120 if (!~uncountables.indexOf(str.toLowerCase())){
1130 found = rules.filter(function(rule){
1140 return str.match(rule[0]);
115 });
1160 if (found[0]) return str.replace(found[0][0], found[0][1]);
117 }
1180 return str;
119};
120
121/*!
122 * Determines if `a` and `b` are deep equal.
123 *
124 * Modified from node/lib/assert.js
125 *
126 * @param {any} a a value to compare to `b`
127 * @param {any} b a value to compare to `a`
128 * @return {Boolean}
129 * @api private
130 */
131
1321exports.deepEqual = function deepEqual (a, b) {
1330 if (a === b) return true;
134
1350 if (a instanceof Date && b instanceof Date)
1360 return a.getTime() === b.getTime();
137
1380 if (a instanceof ObjectId && b instanceof ObjectId) {
1390 return a.toString() === b.toString();
140 }
141
1420 if (a instanceof RegExp && b instanceof RegExp) {
1430 return a.source == b.source &&
144 a.ignoreCase == b.ignoreCase &&
145 a.multiline == b.multiline &&
146 a.global == b.global;
147 }
148
1490 if (typeof a !== 'object' && typeof b !== 'object')
1500 return a == b;
151
1520 if (a === null || b === null || a === undefined || b === undefined)
1530 return false
154
1550 if (a.prototype !== b.prototype) return false;
156
157 // Handle MongooseNumbers
1580 if (a instanceof Number && b instanceof Number) {
1590 return a.valueOf() === b.valueOf();
160 }
161
1620 if (Buffer.isBuffer(a)) {
1630 return exports.buffer.areEqual(a, b);
164 }
165
1660 if (isMongooseObject(a)) a = a.toObject();
1670 if (isMongooseObject(b)) b = b.toObject();
168
1690 try {
1700 var ka = Object.keys(a),
171 kb = Object.keys(b),
172 key, i;
173 } catch (e) {//happens when one is a string literal and the other isn't
1740 return false;
175 }
176
177 // having the same number of owned properties (keys incorporates
178 // hasOwnProperty)
1790 if (ka.length != kb.length)
1800 return false;
181
182 //the same set of keys (although not necessarily the same order),
1830 ka.sort();
1840 kb.sort();
185
186 //~~~cheap key test
1870 for (i = ka.length - 1; i >= 0; i--) {
1880 if (ka[i] != kb[i])
1890 return false;
190 }
191
192 //equivalent values for every corresponding key, and
193 //~~~possibly expensive deep test
1940 for (i = ka.length - 1; i >= 0; i--) {
1950 key = ka[i];
1960 if (!deepEqual(a[key], b[key])) return false;
197 }
198
1990 return true;
200};
201
202/*!
203 * Object clone with Mongoose natives support.
204 *
205 * If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.
206 *
207 * Functions are never cloned.
208 *
209 * @param {Object} obj the object to clone
210 * @param {Object} options
211 * @return {Object} the cloned object
212 * @api private
213 */
214
2151exports.clone = function clone (obj, options) {
21617 if (obj === undefined || obj === null)
2170 return obj;
218
21917 if (Array.isArray(obj))
2200 return cloneArray(obj, options);
221
22217 if (isMongooseObject(obj)) {
2230 if (options && options.json && 'function' === typeof obj.toJSON) {
2240 return obj.toJSON(options);
225 } else {
2260 return obj.toObject(options);
227 }
228 }
229
23017 if (obj.constructor) {
23117 switch (obj.constructor.name) {
232 case 'Object':
2330 return cloneObject(obj, options);
234 case 'Date':
2350 return new obj.constructor(+obj);
236 case 'RegExp':
2370 return cloneRegExp(obj);
238 default:
239 // ignore
24017 break;
241 }
242 }
243
24417 if (obj instanceof ObjectId)
2450 return new ObjectId(obj.id);
246
24717 if (!obj.constructor && exports.isObject(obj)) {
248 // object created with Object.create(null)
2490 return cloneObject(obj, options);
250 }
251
25217 if (obj.valueOf)
25317 return obj.valueOf();
254};
2551var clone = exports.clone;
256
257/*!
258 * ignore
259 */
260
2611function cloneObject (obj, options) {
2620 var retainKeyOrder = options && options.retainKeyOrder
263 , minimize = options && options.minimize
264 , ret = {}
265 , hasKeys
266 , keys
267 , val
268 , k
269 , i
270
2710 if (retainKeyOrder) {
2720 for (k in obj) {
2730 val = clone(obj[k], options);
274
2750 if (!minimize || ('undefined' !== typeof val)) {
2760 hasKeys || (hasKeys = true);
2770 ret[k] = val;
278 }
279 }
280 } else {
281 // faster
282
2830 keys = Object.keys(obj);
2840 i = keys.length;
285
2860 while (i--) {
2870 k = keys[i];
2880 val = clone(obj[k], options);
289
2900 if (!minimize || ('undefined' !== typeof val)) {
2910 if (!hasKeys) hasKeys = true;
2920 ret[k] = val;
293 }
294 }
295 }
296
2970 return minimize
298 ? hasKeys && ret
299 : ret;
300};
301
3021function cloneArray (arr, options) {
3030 var ret = [];
3040 for (var i = 0, l = arr.length; i < l; i++)
3050 ret.push(clone(arr[i], options));
3060 return ret;
307};
308
309/*!
310 * Shallow copies defaults into options.
311 *
312 * @param {Object} defaults
313 * @param {Object} options
314 * @return {Object} the merged object
315 * @api private
316 */
317
3181exports.options = function (defaults, options) {
3191 var keys = Object.keys(defaults)
320 , i = keys.length
321 , k ;
322
3231 options = options || {};
324
3251 while (i--) {
32613 k = keys[i];
32713 if (!(k in options)) {
32811 options[k] = defaults[k];
329 }
330 }
331
3321 return options;
333};
334
335/*!
336 * Generates a random string
337 *
338 * @api private
339 */
340
3411exports.random = function () {
3420 return Math.random().toString().substr(3);
343};
344
345/*!
346 * Merges `from` into `to` without overwriting existing properties.
347 *
348 * @param {Object} to
349 * @param {Object} from
350 * @api private
351 */
352
3531exports.merge = function merge (to, from) {
3540 var keys = Object.keys(from)
355 , i = keys.length
356 , key;
357
3580 while (i--) {
3590 key = keys[i];
3600 if ('undefined' === typeof to[key]) {
3610 to[key] = from[key];
3620 } else if (exports.isObject(from[key])) {
3630 merge(to[key], from[key]);
364 }
365 }
366};
367
368/*!
369 * toString helper
370 */
371
3721var toString = Object.prototype.toString;
373
374/*!
375 * Determines if `arg` is an object.
376 *
377 * @param {Object|Array|String|Function|RegExp|any} arg
378 * @api private
379 * @return {Boolean}
380 */
381
3821exports.isObject = function (arg) {
38317 return '[object Object]' == toString.call(arg);
384}
385
386/*!
387 * A faster Array.prototype.slice.call(arguments) alternative
388 * @api private
389 */
390
3911exports.args = sliced;
392
393/*!
394 * process.nextTick helper.
395 *
396 * Wraps `callback` in a try/catch + nextTick.
397 *
398 * node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.
399 *
400 * @param {Function} callback
401 * @api private
402 */
403
4041exports.tick = function tick (callback) {
4050 if ('function' !== typeof callback) return;
4060 return function () {
4070 try {
4080 callback.apply(this, arguments);
409 } catch (err) {
410 // only nextTick on err to get out of
411 // the event loop and avoid state corruption.
4120 process.nextTick(function () {
4130 throw err;
414 });
415 }
416 }
417}
418
419/*!
420 * Returns if `v` is a mongoose object that has a `toObject()` method we can use.
421 *
422 * This is for compatibility with libs like Date.js which do foolish things to Natives.
423 *
424 * @param {any} v
425 * @api private
426 */
427
4281exports.isMongooseObject = function (v) {
42917 Document || (Document = require('./document'));
43017 MongooseArray || (MongooseArray = require('./types').Array);
43117 MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
432
43317 return v instanceof Document ||
434 v instanceof MongooseArray ||
435 v instanceof MongooseBuffer
436}
4371var isMongooseObject = exports.isMongooseObject;
438
439/*!
440 * Converts `expires` options of index objects to `expiresAfterSeconds` options for MongoDB.
441 *
442 * @param {Object} object
443 * @api private
444 */
445
4461exports.expires = function expires (object) {
4470 if (!(object && 'Object' == object.constructor.name)) return;
4480 if (!('expires' in object)) return;
449
4500 var when;
4510 if ('string' != typeof object.expires) {
4520 when = object.expires;
453 } else {
4540 when = Math.round(ms(object.expires) / 1000);
455 }
4560 object.expireAfterSeconds = when;
4570 delete object.expires;
458}
459
460/*!
461 * Converts arguments to ReadPrefs the driver
462 * can understand.
463 *
464 * @TODO move this into the driver layer
465 * @param {String|Array} pref
466 * @param {Array} [tags]
467 */
468
4691exports.readPref = function readPref (pref, tags) {
4700 if (Array.isArray(pref)) {
4710 tags = pref[1];
4720 pref = pref[0];
473 }
474
4750 switch (pref) {
476 case 'p':
4770 pref = 'primary';
4780 break;
479 case 'pp':
4800 pref = 'primaryPreferred';
4810 break;
482 case 's':
4830 pref = 'secondary';
4840 break;
485 case 'sp':
4860 pref = 'secondaryPreferred';
4870 break;
488 case 'n':
4890 pref = 'nearest';
4900 break;
491 }
492
4930 return new ReadPref(pref, tags);
494}
495
496/*!
497 * Populate options constructor
498 */
499
5001function PopulateOptions (path, select, match, options, model) {
5010 this.path = path;
5020 this.match = match;
5030 this.select = select;
5040 this.options = options;
5050 this.model = model;
5060 this._docs = {};
507}
508
509// make it compatible with utils.clone
5101PopulateOptions.prototype.constructor = Object;
511
512// expose
5131exports.PopulateOptions = PopulateOptions;
514
515/*!
516 * populate helper
517 */
518
5191exports.populate = function populate (path, select, model, match, options) {
520 // The order of select/conditions args is opposite Model.find but
521 // necessary to keep backward compatibility (select could be
522 // an array, string, or object literal).
523
524 // might have passed an object specifying all arguments
5250 if (1 === arguments.length) {
5260 if (path instanceof PopulateOptions) {
5270 return [path];
528 }
529
5300 if (Array.isArray(path)) {
5310 return path.map(function(o){
5320 return exports.populate(o)[0];
533 });
534 }
535
5360 if (exports.isObject(path)) {
5370 match = path.match;
5380 options = path.options;
5390 select = path.select;
5400 model = path.model;
5410 path = path.path;
542 }
5430 } else if ('string' !== typeof model) {
5440 options = match;
5450 match = model;
5460 model = undefined;
547 }
548
5490 if ('string' != typeof path) {
5500 throw new TypeError('utils.populate: invalid path. Expected string. Got typeof `' + typeof path + '`');
551 }
552
5530 var ret = [];
5540 var paths = path.split(' ');
5550 for (var i = 0; i < paths.length; ++i) {
5560 ret.push(new PopulateOptions(paths[i], select, match, options, model));
557 }
558
5590 return ret;
560}
561
562/*!
563 * Return the value of `obj` at the given `path`.
564 *
565 * @param {String} path
566 * @param {Object} obj
567 */
568
5691exports.getValue = function (path, obj, map) {
5700 return mpath.get(path, obj, '_doc', map);
571}
572
573/*!
574 * Sets the value of `obj` at the given `path`.
575 *
576 * @param {String} path
577 * @param {Anything} val
578 * @param {Object} obj
579 */
580
5811exports.setValue = function (path, val, obj, map) {
5820 mpath.set(path, val, obj, '_doc', map);
583}
584
585/*!
586 * Returns an array of values from object `o`.
587 *
588 * @param {Object} o
589 * @return {Array}
590 * @private
591 */
592
5931exports.object = {};
5941exports.object.vals = function vals (o) {
5950 var keys = Object.keys(o)
596 , i = keys.length
597 , ret = [];
598
5990 while (i--) {
6000 ret.push(o[keys[i]]);
601 }
602
6030 return ret;
604}
605
606/*!
607 * @see exports.options
608 */
609
6101exports.object.shallowCopy = exports.options;
611
612/*!
613 * Safer helper for hasOwnProperty checks
614 *
615 * @param {Object} obj
616 * @param {String} prop
617 */
618
6191var hop = Object.prototype.hasOwnProperty;
6201exports.object.hasOwnProperty = function (obj, prop) {
6210 return hop.call(obj, prop);
622}
623
624/*!
625 * Determine if `val` is null or undefined
626 *
627 * @return {Boolean}
628 */
629
6301exports.isNullOrUndefined = function (val) {
6310 return null == val
632}
633
634/*!
635 * ignore
636 */
637
6381exports.array = {};
639
640/*!
641 * Flattens an array.
642 *
643 * [ 1, [ 2, 3, [4] ]] -> [1,2,3,4]
644 *
645 * @param {Array} arr
646 * @param {Function} [filter] If passed, will be invoked with each item in the array. If `filter` returns a falsey value, the item will not be included in the results.
647 * @return {Array}
648 * @private
649 */
650
6511exports.array.flatten = function flatten (arr, filter, ret) {
6520 ret || (ret = []);
653
6540 arr.forEach(function (item) {
6550 if (Array.isArray(item)) {
6560 flatten(item, filter, ret);
657 } else {
6580 if (!filter || filter(item)) {
6590 ret.push(item);
660 }
661 }
662 });
663
6640 return ret;
665}
666
667/*!
668 * Determines if two buffers are equal.
669 *
670 * @param {Buffer} a
671 * @param {Object} b
672 */
673
6741exports.buffer = {};
6751exports.buffer.areEqual = function (a, b) {
6760 if (!Buffer.isBuffer(a)) return false;
6770 if (!Buffer.isBuffer(b)) return false;
6780 if (a.length !== b.length) return false;
6790 for (var i = 0, len = a.length; i < len; ++i) {
6800 if (a[i] !== b[i]) return false;
681 }
6820 return true;
683}
684
685

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/lib/virtualtype.js

27%
22
6
16
LineHitsSource
1
2/**
3 * VirtualType constructor
4 *
5 * This is what mongoose uses to define virtual attributes via `Schema.prototype.virtual`.
6 *
7 * ####Example:
8 *
9 * var fullname = schema.virtual('fullname');
10 * fullname instanceof mongoose.VirtualType // true
11 *
12 * @parma {Object} options
13 * @api public
14 */
15
161function VirtualType (options, name) {
170 this.path = name;
180 this.getters = [];
190 this.setters = [];
200 this.options = options || {};
21}
22
23/**
24 * Defines a getter.
25 *
26 * ####Example:
27 *
28 * var virtual = schema.virtual('fullname');
29 * virtual.get(function () {
30 * return this.name.first + ' ' + this.name.last;
31 * });
32 *
33 * @param {Function} fn
34 * @return {VirtualType} this
35 * @api public
36 */
37
381VirtualType.prototype.get = function (fn) {
390 this.getters.push(fn);
400 return this;
41};
42
43/**
44 * Defines a setter.
45 *
46 * ####Example:
47 *
48 * var virtual = schema.virtual('fullname');
49 * virtual.set(function (v) {
50 * var parts = v.split(' ');
51 * this.name.first = parts[0];
52 * this.name.last = parts[1];
53 * });
54 *
55 * @param {Function} fn
56 * @return {VirtualType} this
57 * @api public
58 */
59
601VirtualType.prototype.set = function (fn) {
610 this.setters.push(fn);
620 return this;
63};
64
65/**
66 * Applies getters to `value` using optional `scope`.
67 *
68 * @param {Object} value
69 * @param {Object} scope
70 * @return {any} the value after applying all getters
71 * @api public
72 */
73
741VirtualType.prototype.applyGetters = function (value, scope) {
750 var v = value;
760 for (var l = this.getters.length - 1; l >= 0; l--) {
770 v = this.getters[l].call(scope, v, this);
78 }
790 return v;
80};
81
82/**
83 * Applies setters to `value` using optional `scope`.
84 *
85 * @param {Object} value
86 * @param {Object} scope
87 * @return {any} the value after applying all setters
88 * @api public
89 */
90
911VirtualType.prototype.applySetters = function (value, scope) {
920 var v = value;
930 for (var l = this.setters.length - 1; l >= 0; l--) {
940 v = this.setters[l].call(scope, v, this);
95 }
960 return v;
97};
98
99/*!
100 * exports
101 */
102
1031module.exports = VirtualType;
104

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/admin.js

15%
116
18
98
LineHitsSource
1/*!
2 * Module dependencies.
3 */
41var Collection = require('./collection').Collection,
5 Cursor = require('./cursor').Cursor,
6 DbCommand = require('./commands/db_command').DbCommand,
7 utils = require('./utils');
8
9/**
10 * Allows the user to access the admin functionality of MongoDB
11 *
12 * @class Represents the Admin methods of MongoDB.
13 * @param {Object} db Current db instance we wish to perform Admin operations on.
14 * @return {Function} Constructor for Admin type.
15 */
161function Admin(db) {
170 if(!(this instanceof Admin)) return new Admin(db);
180 this.db = db;
19};
20
21/**
22 * Retrieve the server information for the current
23 * instance of the db client
24 *
25 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from buildInfo or null if an error occured.
26 * @return {null} Returns no result
27 * @api public
28 */
291Admin.prototype.buildInfo = function(callback) {
300 this.serverInfo(callback);
31}
32
33/**
34 * Retrieve the server information for the current
35 * instance of the db client
36 *
37 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverInfo or null if an error occured.
38 * @return {null} Returns no result
39 * @api private
40 */
411Admin.prototype.serverInfo = function(callback) {
420 this.db.executeDbAdminCommand({buildinfo:1}, function(err, doc) {
430 if(err != null) return callback(err, null);
440 return callback(null, doc.documents[0]);
45 });
46}
47
48/**
49 * Retrieve this db's server status.
50 *
51 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverStatus or null if an error occured.
52 * @return {null}
53 * @api public
54 */
551Admin.prototype.serverStatus = function(callback) {
560 var self = this;
57
580 this.db.executeDbAdminCommand({serverStatus: 1}, function(err, doc) {
590 if(err == null && doc.documents[0].ok === 1) {
600 callback(null, doc.documents[0]);
61 } else {
620 if(err) return callback(err, false);
630 return callback(utils.toError(doc.documents[0]), false);
64 }
65 });
66};
67
68/**
69 * Retrieve the current profiling Level for MongoDB
70 *
71 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingLevel or null if an error occured.
72 * @return {null} Returns no result
73 * @api public
74 */
751Admin.prototype.profilingLevel = function(callback) {
760 var self = this;
77
780 this.db.executeDbAdminCommand({profile:-1}, function(err, doc) {
790 doc = doc.documents[0];
80
810 if(err == null && doc.ok === 1) {
820 var was = doc.was;
830 if(was == 0) return callback(null, "off");
840 if(was == 1) return callback(null, "slow_only");
850 if(was == 2) return callback(null, "all");
860 return callback(new Error("Error: illegal profiling level value " + was), null);
87 } else {
880 err != null ? callback(err, null) : callback(new Error("Error with profile command"), null);
89 }
90 });
91};
92
93/**
94 * Ping the MongoDB server and retrieve results
95 *
96 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from ping or null if an error occured.
97 * @return {null} Returns no result
98 * @api public
99 */
1001Admin.prototype.ping = function(options, callback) {
101 // Unpack calls
1020 var args = Array.prototype.slice.call(arguments, 0);
1030 callback = args.pop();
104
1050 this.db.executeDbAdminCommand({ping: 1}, callback);
106}
107
108/**
109 * Authenticate against MongoDB
110 *
111 * @param {String} username The user name for the authentication.
112 * @param {String} password The password for the authentication.
113 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from authenticate or null if an error occured.
114 * @return {null} Returns no result
115 * @api public
116 */
1171Admin.prototype.authenticate = function(username, password, callback) {
1180 this.db.authenticate(username, password, {authdb: 'admin'}, function(err, doc) {
1190 return callback(err, doc);
120 })
121}
122
123/**
124 * Logout current authenticated user
125 *
126 * @param {Object} [options] Optional parameters to the command.
127 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from logout or null if an error occured.
128 * @return {null} Returns no result
129 * @api public
130 */
1311Admin.prototype.logout = function(callback) {
1320 this.db.logout({authdb: 'admin'}, function(err, doc) {
1330 return callback(err, doc);
134 })
135}
136
137/**
138 * Add a user to the MongoDB server, if the user exists it will
139 * overwrite the current password
140 *
141 * Options
142 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
143 *
144 * @param {String} username The user name for the authentication.
145 * @param {String} password The password for the authentication.
146 * @param {Object} [options] additional options during update.
147 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from addUser or null if an error occured.
148 * @return {null} Returns no result
149 * @api public
150 */
1511Admin.prototype.addUser = function(username, password, options, callback) {
1520 var args = Array.prototype.slice.call(arguments, 2);
1530 callback = args.pop();
1540 options = args.length ? args.shift() : {};
155 // Set the db name to admin
1560 options.dbName = 'admin';
157 // Add user
1580 this.db.addUser(username, password, options, function(err, doc) {
1590 return callback(err, doc);
160 })
161}
162
163/**
164 * Remove a user from the MongoDB server
165 *
166 * Options
167 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
168 *
169 * @param {String} username The user name for the authentication.
170 * @param {Object} [options] additional options during update.
171 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occured.
172 * @return {null} Returns no result
173 * @api public
174 */
1751Admin.prototype.removeUser = function(username, options, callback) {
1760 var self = this;
1770 var args = Array.prototype.slice.call(arguments, 1);
1780 callback = args.pop();
1790 options = args.length ? args.shift() : {};
1800 options.dbName = 'admin';
181
1820 this.db.removeUser(username, options, function(err, doc) {
1830 return callback(err, doc);
184 })
185}
186
187/**
188 * Set the current profiling level of MongoDB
189 *
190 * @param {String} level The new profiling level (off, slow_only, all)
191 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from setProfilingLevel or null if an error occured.
192 * @return {null} Returns no result
193 * @api public
194 */
1951Admin.prototype.setProfilingLevel = function(level, callback) {
1960 var self = this;
1970 var command = {};
1980 var profile = 0;
199
2000 if(level == "off") {
2010 profile = 0;
2020 } else if(level == "slow_only") {
2030 profile = 1;
2040 } else if(level == "all") {
2050 profile = 2;
206 } else {
2070 return callback(new Error("Error: illegal profiling level value " + level));
208 }
209
210 // Set up the profile number
2110 command['profile'] = profile;
212
2130 this.db.executeDbAdminCommand(command, function(err, doc) {
2140 doc = doc.documents[0];
215
2160 if(err == null && doc.ok === 1)
2170 return callback(null, level);
2180 return err != null ? callback(err, null) : callback(new Error("Error with profile command"), null);
219 });
220};
221
222/**
223 * Retrive the current profiling information for MongoDB
224 *
225 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingInfo or null if an error occured.
226 * @return {null} Returns no result
227 * @api public
228 */
2291Admin.prototype.profilingInfo = function(callback) {
2300 try {
2310 new Cursor(this.db, new Collection(this.db, DbCommand.SYSTEM_PROFILE_COLLECTION), {}, {}, {dbName: 'admin'}).toArray(function(err, items) {
2320 return callback(err, items);
233 });
234 } catch (err) {
2350 return callback(err, null);
236 }
237};
238
239/**
240 * Execute a db command against the Admin database
241 *
242 * @param {Object} command A command object `{ping:1}`.
243 * @param {Object} [options] Optional parameters to the command.
244 * @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter.
245 * @return {null} Returns no result
246 * @api public
247 */
2481Admin.prototype.command = function(command, options, callback) {
2490 var self = this;
2500 var args = Array.prototype.slice.call(arguments, 1);
2510 callback = args.pop();
2520 options = args.length ? args.shift() : {};
253
254 // Execute a command
2550 this.db.executeDbAdminCommand(command, options, function(err, doc) {
256 // Ensure change before event loop executes
2570 return callback != null ? callback(err, doc) : null;
258 });
259}
260
261/**
262 * Validate an existing collection
263 *
264 * @param {String} collectionName The name of the collection to validate.
265 * @param {Object} [options] Optional parameters to the command.
266 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from validateCollection or null if an error occured.
267 * @return {null} Returns no result
268 * @api public
269 */
2701Admin.prototype.validateCollection = function(collectionName, options, callback) {
2710 var args = Array.prototype.slice.call(arguments, 1);
2720 callback = args.pop();
2730 options = args.length ? args.shift() : {};
274
2750 var self = this;
2760 var command = {validate: collectionName};
2770 var keys = Object.keys(options);
278
279 // Decorate command with extra options
2800 for(var i = 0; i < keys.length; i++) {
2810 if(options.hasOwnProperty(keys[i])) {
2820 command[keys[i]] = options[keys[i]];
283 }
284 }
285
2860 this.db.executeDbCommand(command, function(err, doc) {
2870 if(err != null) return callback(err, null);
2880 doc = doc.documents[0];
289
2900 if(doc.ok === 0)
2910 return callback(new Error("Error with validate command"), null);
2920 if(doc.result != null && doc.result.constructor != String)
2930 return callback(new Error("Error with validation data"), null);
2940 if(doc.result != null && doc.result.match(/exception|corrupt/) != null)
2950 return callback(new Error("Error: invalid collection " + collectionName), null);
2960 if(doc.valid != null && !doc.valid)
2970 return callback(new Error("Error: invalid collection " + collectionName), null);
298
2990 return callback(null, doc);
300 });
301};
302
303/**
304 * List the available databases
305 *
306 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from listDatabases or null if an error occured.
307 * @return {null} Returns no result
308 * @api public
309 */
3101Admin.prototype.listDatabases = function(callback) {
311 // Execute the listAllDatabases command
3120 this.db.executeDbAdminCommand({listDatabases:1}, {}, function(err, doc) {
3130 if(err != null) return callback(err, null);
3140 return callback(null, doc.documents[0]);
315 });
316}
317
318/**
319 * Get ReplicaSet status
320 *
321 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from replSetGetStatus or null if an error occured.
322 * @return {null}
323 * @api public
324 */
3251Admin.prototype.replSetGetStatus = function(callback) {
3260 var self = this;
327
3280 this.db.executeDbAdminCommand({replSetGetStatus:1}, function(err, doc) {
3290 if(err == null && doc.documents[0].ok === 1)
3300 return callback(null, doc.documents[0]);
3310 if(err) return callback(err, false);
3320 return callback(utils.toError(doc.documents[0]), false);
333 });
334};
335
336/**
337 * @ignore
338 */
3391exports.Admin = Admin;
340

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/aggregation_cursor.js

6%
82
5
77
LineHitsSource
11var ReadPreference = require('./connection/read_preference').ReadPreference
2 , Readable = require('stream').Readable
3 , CommandCursor = require('./command_cursor').CommandCursor
4 , utils = require('./utils')
5 , shared = require('./collection/shared')
6 , inherits = require('util').inherits;
7
81var AggregationCursor = function(collection, serverCapabilities, options) {
90 var pipe = [];
100 var self = this;
110 var results = null;
120 var _cursor_options = {};
13 // Ensure we have options set up
140 options = options == null ? {} : options;
15
16 // If a pipeline was provided
170 pipe = Array.isArray(options.pipe) ? options.pipe : pipe;
18 // Set passed in batchSize if provided
190 if(typeof options.batchSize == 'number') _cursor_options.batchSize = options.batchSize;
20 // Get the read Preference
210 var readPreference = shared._getReadConcern(collection, options);
22
23 // Set up
240 Readable.call(this, {objectMode: true});
25
26 // Contains connection
270 var connection = null;
28
29 // Set the read preference
300 var _options = {
31 readPreference: readPreference
32 };
33
34 // Actual command
350 var command = {
36 aggregate: collection.collectionName
37 , pipeline: pipe
38 , cursor: _cursor_options
39 }
40
41 // If allowDiskUsage is set
420 if(typeof options.allowDiskUsage == 'boolean')
430 command.allowDiskUsage = options.allowDiskUsage;
44
45 // Command cursor (if we support one)
460 var commandCursor = new CommandCursor(collection.db, collection, command);
47
48 // // Internal cursor methods
49 // this.find = function(selector) {
50 // pipe.push({$match: selector});
51 // return self;
52 // }
53
54 // this.unwind = function(unwind) {
55 // pipe.push({$unwind: unwind});
56 // return self;
57 // }
58
59 // this.group = function(group) {
60 // pipe.push({$group: group});
61 // return self;
62 // }
63
64 // this.project = function(project) {
65 // pipe.push({$project: project});
66 // return self;
67 // }
68
69 // this.limit = function(limit) {
70 // pipe.push({$limit: limit});
71 // return self;
72 // }
73
74 // this.geoNear = function(geoNear) {
75 // pipe.push({$geoNear: geoNear});
76 // return self;
77 // }
78
79 // this.sort = function(sort) {
80 // pipe.push({$sort: sort});
81 // return self;
82 // }
83
84 // this.withReadPreference = function(read_preference) {
85 // _options.readPreference = read_preference;
86 // return self;
87 // }
88
89 // this.withQueryOptions = function(options) {
90 // if(options.batchSize) {
91 // _cursor_options.batchSize = options.batchSize;
92 // }
93
94 // // Return the cursor
95 // return self;
96 // }
97
98 // this.skip = function(skip) {
99 // pipe.push({$skip: skip});
100 // return self;
101 // }
102
103 // this.allowDiskUsage = function(allowDiskUsage) {
104 // command.allowDiskUsage = allowDiskUsage;
105 // return self;
106 // }
107
1080 this.explain = function(callback) {
1090 if(typeof callback != 'function')
1100 throw utils.toError("AggregationCursor explain requires a callback function");
111
112 // Add explain options
1130 _options.explain = true;
114 // Execute aggregation pipeline
1150 collection.aggregate(pipe, _options, function(err, results) {
1160 if(err) return callback(err, null);
1170 callback(null, results);
118 });
119 }
120
121 // this.maxTimeMS = function(maxTimeMS) {
122 // if(typeof maxTimeMS != 'number') {
123 // throw new Error("maxTimeMS must be a number");
124 // }
125
126 // // Save the maxTimeMS
127 // _options.maxTimeMS = maxTimeMS
128 // // Set the maxTimeMS on the command cursor
129 // commandCursor.maxTimeMS(maxTimeMS);
130 // return self;
131 // }
132
1330 this.get = function(callback) {
1340 if(typeof callback != 'function')
1350 throw utils.toError("AggregationCursor get requires a callback function");
136 // Checkout a connection
1370 var _connection = collection.db.serverConfig.checkoutReader(_options.readPreference);
138 // Fall back
1390 if(!_connection.serverCapabilities.hasAggregationCursor) {
1400 return collection.aggregate(pipe, _options, function(err, results) {
1410 if(err) return callback(err);
1420 callback(null, results);
143 });
144 }
145
146 // Execute get using command Cursor
1470 commandCursor.get({connection: _connection}, callback);
148 }
149
1500 this.getOne = function(callback) {
1510 if(typeof callback != 'function')
1520 throw utils.toError("AggregationCursor getOne requires a callback function");
153 // Set the limit to 1
1540 pipe.push({$limit: 1});
155 // For now we have no cursor command so let's just wrap existing results
1560 collection.aggregate(pipe, _options, function(err, results) {
1570 if(err) return callback(err);
1580 callback(null, results[0]);
159 });
160 }
161
1620 this.each = function(callback) {
163 // Checkout a connection if we have none
1640 if(!connection)
1650 connection = collection.db.serverConfig.checkoutReader(_options.readPreference);
166
167 // Fall back
1680 if(!connection.serverCapabilities.hasAggregationCursor) {
1690 collection.aggregate(pipe, _options, function(err, _results) {
1700 if(err) return callback(err);
171
1720 while(_results.length > 0) {
1730 callback(null, _results.shift());
174 }
175
1760 callback(null, null);
177 });
178 }
179
180 // Execute each using command Cursor
1810 commandCursor.each({connection: connection}, callback);
182 }
183
1840 this.next = function(callback) {
1850 if(typeof callback != 'function')
1860 throw utils.toError("AggregationCursor next requires a callback function");
187
188 // Checkout a connection if we have none
1890 if(!connection)
1900 connection = collection.db.serverConfig.checkoutReader(_options.readPreference);
191
192 // Fall back
1930 if(!connection.serverCapabilities.hasAggregationCursor) {
1940 if(!results) {
195 // For now we have no cursor command so let's just wrap existing results
1960 return collection.aggregate(pipe, _options, function(err, _results) {
1970 if(err) return callback(err);
1980 results = _results;
199
200 // Ensure we don't issue undefined
2010 var item = results.shift();
2020 callback(null, item ? item : null);
203 });
204 }
205
206 // Ensure we don't issue undefined
2070 var item = results.shift();
208 // Return the item
2090 return callback(null, item ? item : null);
210 }
211
212 // Execute next using command Cursor
2130 commandCursor.next({connection: connection}, callback);
214 }
215
216 //
217 // Close method
218 //
2190 this.close = function(callback) {
2200 if(typeof callback != 'function')
2210 throw utils.toError("AggregationCursor close requires a callback function");
222
223 // Checkout a connection if we have none
2240 if(!connection)
2250 connection = collection.db.serverConfig.checkoutReader(_options.readPreference);
226
227 // Fall back
2280 if(!connection.serverCapabilities.hasAggregationCursor) {
2290 return callback(null, null);
230 }
231
232 // Execute next using command Cursor
2330 commandCursor.close({connection: connection}, callback);
234 }
235
236 //
237 // Stream method
238 //
2390 this._read = function(n) {
2400 self.next(function(err, result) {
2410 if(err) {
2420 self.emit('error', err);
2430 return self.push(null);
244 }
245
2460 self.push(result);
247 });
248 }
249}
250
251// Inherit from Readable
2521if(Readable != null) {
2531 inherits(AggregationCursor, Readable);
254}
255
256// Exports the Aggregation Framework
2571exports.AggregationCursor = AggregationCursor;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js

12%
25
3
22
LineHitsSource
11var DbCommand = require('../commands/db_command').DbCommand
2 , utils = require('../utils');
3
41var authenticate = function(db, username, password, authdb, options, callback) {
50 var numberOfConnections = 0;
60 var errorObject = null;
7
80 if(options['connection'] != null) {
9 //if a connection was explicitly passed on options, then we have only one...
100 numberOfConnections = 1;
11 } else {
12 // Get the amount of connections in the pool to ensure we have authenticated all comments
130 numberOfConnections = db.serverConfig.allRawConnections().length;
140 options['onAll'] = true;
15 }
16
17 // Execute all four
180 db._executeQueryCommand(DbCommand.createGetNonceCommand(db), options, function(err, result, connection) {
19 // console.log("--------------------------------------------- MONGODB-CR 0")
20 // console.dir(err)
21 // Execute on all the connections
220 if(err == null) {
23 // Nonce used to make authentication request with md5 hash
240 var nonce = result.documents[0].nonce;
25 // Execute command
260 db._executeQueryCommand(DbCommand.createAuthenticationCommand(db, username, password, nonce, authdb), {connection:connection}, function(err, result) {
27 // console.log("--------------------------------------------- MONGODB-CR 1")
28 // console.dir(err)
29 // console.dir(result)
30 // Count down
310 numberOfConnections = numberOfConnections - 1;
32 // Ensure we save any error
330 if(err) {
340 errorObject = err;
350 } else if(result
36 && Array.isArray(result.documents)
37 && result.documents.length > 0
38 && (result.documents[0].err != null || result.documents[0].errmsg != null)) {
390 errorObject = utils.toError(result.documents[0]);
40 }
41
42 // Work around the case where the number of connections are 0
430 if(numberOfConnections <= 0 && typeof callback == 'function') {
440 var internalCallback = callback;
450 callback = null;
46
470 if(errorObject == null
48 && result && Array.isArray(result.documents) && result.documents.length > 0
49 && result.documents[0].ok == 1) { // We authenticated correctly save the credentials
500 db.serverConfig.auth.add('MONGODB-CR', db.databaseName, username, password, authdb);
51 // Return callback
520 internalCallback(errorObject, true);
53 } else {
540 internalCallback(errorObject, false);
55 }
56 }
57 });
58 }
59 });
60}
61
621exports.authenticate = authenticate;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js

21%
57
12
45
LineHitsSource
11var DbCommand = require('../commands/db_command').DbCommand
2 , utils = require('../utils')
3 , format = require('util').format;
4
5// Kerberos class
61var Kerberos = null;
71var MongoAuthProcess = null;
8// Try to grab the Kerberos class
91try {
101 Kerberos = require('kerberos').Kerberos
11 // Authentication process for Mongo
121 MongoAuthProcess = require('kerberos').processes.MongoAuthProcess
13} catch(err) {}
14
151var authenticate = function(db, username, password, authdb, options, callback) {
160 var numberOfConnections = 0;
170 var errorObject = null;
18 // We don't have the Kerberos library
190 if(Kerberos == null) return callback(new Error("Kerberos library is not installed"));
20
210 if(options['connection'] != null) {
22 //if a connection was explicitly passed on options, then we have only one...
230 numberOfConnections = 1;
24 } else {
25 // Get the amount of connections in the pool to ensure we have authenticated all comments
260 numberOfConnections = db.serverConfig.allRawConnections().length;
270 options['onAll'] = true;
28 }
29
30 // Grab all the connections
310 var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections();
320 var gssapiServiceName = options['gssapiServiceName'] || 'mongodb';
330 var error = null;
34 // Authenticate all connections
350 for(var i = 0; i < numberOfConnections; i++) {
36
37 // Start Auth process for a connection
380 GSSAPIInitialize(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) {
39 // Adjust number of connections left to connect
400 numberOfConnections = numberOfConnections - 1;
41 // If we have an error save it
420 if(err) error = err;
43
44 // We are done
450 if(numberOfConnections == 0) {
460 if(err) return callback(error, false);
47 // We authenticated correctly save the credentials
480 db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName);
49 // Return valid callback
500 return callback(null, true);
51 }
52 });
53 }
54}
55
56//
57// Initialize step
581var GSSAPIInitialize = function(db, username, password, authdb, gssapiServiceName, connection, callback) {
59 // Create authenticator
600 var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, gssapiServiceName);
61
62 // Perform initialization
630 mongo_auth_process.init(username, password, function(err, context) {
640 if(err) return callback(err, false);
65
66 // Perform the first step
670 mongo_auth_process.transition('', function(err, payload) {
680 if(err) return callback(err, false);
69
70 // Call the next db step
710 MongoDBGSSAPIFirstStep(mongo_auth_process, payload, db, username, password, authdb, connection, callback);
72 });
73 });
74}
75
76//
77// Perform first step against mongodb
781var MongoDBGSSAPIFirstStep = function(mongo_auth_process, payload, db, username, password, authdb, connection, callback) {
79 // Build the sasl start command
800 var command = {
81 saslStart: 1
82 , mechanism: 'GSSAPI'
83 , payload: payload
84 , autoAuthorize: 1
85 };
86
87 // Execute first sasl step
880 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
890 if(err) return callback(err, false);
90 // Get the payload
910 doc = doc.documents[0];
920 var db_payload = doc.payload;
93
940 mongo_auth_process.transition(doc.payload, function(err, payload) {
950 if(err) return callback(err, false);
96
97 // MongoDB API Second Step
980 MongoDBGSSAPISecondStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback);
99 });
100 });
101}
102
103//
104// Perform first step against mongodb
1051var MongoDBGSSAPISecondStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) {
106 // Build Authentication command to send to MongoDB
1070 var command = {
108 saslContinue: 1
109 , conversationId: doc.conversationId
110 , payload: payload
111 };
112
113 // Execute the command
1140 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
1150 if(err) return callback(err, false);
116
117 // Get the result document
1180 doc = doc.documents[0];
119
120 // Call next transition for kerberos
1210 mongo_auth_process.transition(doc.payload, function(err, payload) {
1220 if(err) return callback(err, false);
123
124 // Call the last and third step
1250 MongoDBGSSAPIThirdStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback);
126 });
127 });
128}
129
1301var MongoDBGSSAPIThirdStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) {
131 // Build final command
1320 var command = {
133 saslContinue: 1
134 , conversationId: doc.conversationId
135 , payload: payload
136 };
137
138 // Let's finish the auth process against mongodb
1390 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
1400 if(err) return callback(err, false);
141
1420 mongo_auth_process.transition(null, function(err, payload) {
1430 if(err) return callback(err, false);
1440 callback(null, true);
145 });
146 });
147}
148
1491exports.authenticate = authenticate;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js

11%
27
3
24
LineHitsSource
11var DbCommand = require('../commands/db_command').DbCommand
2 , utils = require('../utils')
3 , Binary = require('bson').Binary
4 , format = require('util').format;
5
61var authenticate = function(db, username, password, options, callback) {
70 var numberOfConnections = 0;
80 var errorObject = null;
9
100 if(options['connection'] != null) {
11 //if a connection was explicitly passed on options, then we have only one...
120 numberOfConnections = 1;
13 } else {
14 // Get the amount of connections in the pool to ensure we have authenticated all comments
150 numberOfConnections = db.serverConfig.allRawConnections().length;
160 options['onAll'] = true;
17 }
18
19 // Create payload
200 var payload = new Binary(format("\x00%s\x00%s", username, password));
21
22 // Let's start the sasl process
230 var command = {
24 saslStart: 1
25 , mechanism: 'PLAIN'
26 , payload: payload
27 , autoAuthorize: 1
28 };
29
30 // Grab all the connections
310 var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections();
32
33 // Authenticate all connections
340 for(var i = 0; i < numberOfConnections; i++) {
350 var connection = connections[i];
36 // Execute first sasl step
370 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, result) {
38 // Count down
390 numberOfConnections = numberOfConnections - 1;
40
41 // Ensure we save any error
420 if(err) {
430 errorObject = err;
440 } else if(result.documents[0].err != null || result.documents[0].errmsg != null){
450 errorObject = utils.toError(result.documents[0]);
46 }
47
48 // Work around the case where the number of connections are 0
490 if(numberOfConnections <= 0 && typeof callback == 'function') {
500 var internalCallback = callback;
510 callback = null;
52
530 if(errorObject == null && result.documents[0].ok == 1) {
54 // We authenticated correctly save the credentials
550 db.serverConfig.auth.add('PLAIN', db.databaseName, username, password);
56 // Return callback
570 internalCallback(errorObject, true);
58 } else {
590 internalCallback(errorObject, false);
60 }
61 }
62 });
63 }
64}
65
661exports.authenticate = authenticate;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js

16%
53
9
44
LineHitsSource
11var DbCommand = require('../commands/db_command').DbCommand
2 , utils = require('../utils')
3 , format = require('util').format;
4
5// Kerberos class
61var Kerberos = null;
71var MongoAuthProcess = null;
8// Try to grab the Kerberos class
91try {
101 Kerberos = require('kerberos').Kerberos
11 // Authentication process for Mongo
121 MongoAuthProcess = require('kerberos').processes.MongoAuthProcess
13} catch(err) {}
14
151var authenticate = function(db, username, password, authdb, options, callback) {
160 var numberOfConnections = 0;
170 var errorObject = null;
18 // We don't have the Kerberos library
190 if(Kerberos == null) return callback(new Error("Kerberos library is not installed"));
20
210 if(options['connection'] != null) {
22 //if a connection was explicitly passed on options, then we have only one...
230 numberOfConnections = 1;
24 } else {
25 // Get the amount of connections in the pool to ensure we have authenticated all comments
260 numberOfConnections = db.serverConfig.allRawConnections().length;
270 options['onAll'] = true;
28 }
29
30 // Set the sspi server name
310 var gssapiServiceName = options['gssapiServiceName'] || 'mongodb';
32
33 // Grab all the connections
340 var connections = db.serverConfig.allRawConnections();
350 var error = null;
36
37 // Authenticate all connections
380 for(var i = 0; i < numberOfConnections; i++) {
39 // Start Auth process for a connection
400 SSIPAuthenticate(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) {
41 // Adjust number of connections left to connect
420 numberOfConnections = numberOfConnections - 1;
43 // If we have an error save it
440 if(err) error = err;
45
46 // We are done
470 if(numberOfConnections == 0) {
480 if(err) return callback(err, false);
49 // We authenticated correctly save the credentials
500 db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName);
51 // Return valid callback
520 return callback(null, true);
53 }
54 });
55 }
56}
57
581var SSIPAuthenticate = function(db, username, password, authdb, service_name, connection, callback) {
59 // --------------------------------------------------------------
60 // Async Version
61 // --------------------------------------------------------------
620 var command = {
63 saslStart: 1
64 , mechanism: 'GSSAPI'
65 , payload: ''
66 , autoAuthorize: 1
67 };
68
69 // Create authenticator
700 var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, service_name);
71
72 // Execute first sasl step
730 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
740 if(err) return callback(err);
750 doc = doc.documents[0];
76
770 mongo_auth_process.init(username, password, function(err) {
780 if(err) return callback(err);
79
800 mongo_auth_process.transition(doc.payload, function(err, payload) {
810 if(err) return callback(err);
82
83 // Perform the next step against mongod
840 var command = {
85 saslContinue: 1
86 , conversationId: doc.conversationId
87 , payload: payload
88 };
89
90 // Execute the command
910 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
920 if(err) return callback(err);
930 doc = doc.documents[0];
94
950 mongo_auth_process.transition(doc.payload, function(err, payload) {
960 if(err) return callback(err);
97
98 // Perform the next step against mongod
990 var command = {
100 saslContinue: 1
101 , conversationId: doc.conversationId
102 , payload: payload
103 };
104
105 // Execute the command
1060 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
1070 if(err) return callback(err);
1080 doc = doc.documents[0];
109
1100 mongo_auth_process.transition(doc.payload, function(err, payload) {
111 // Perform the next step against mongod
1120 var command = {
113 saslContinue: 1
114 , conversationId: doc.conversationId
115 , payload: payload
116 };
117
118 // Execute the command
1190 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
1200 if(err) return callback(err);
1210 doc = doc.documents[0];
122
1230 if(doc.done) return callback(null, true);
1240 callback(new Error("Authentication failed"), false);
125 });
126 });
127 });
128 });
129 });
130 });
131 });
132 });
133}
134
1351exports.authenticate = authenticate;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_x509.js

11%
26
3
23
LineHitsSource
11var DbCommand = require('../commands/db_command').DbCommand
2 , utils = require('../utils')
3 , Binary = require('bson').Binary
4 , format = require('util').format;
5
61var authenticate = function(db, username, password, options, callback) {
70 var numberOfConnections = 0;
80 var errorObject = null;
9
100 if(options['connection'] != null) {
11 //if a connection was explicitly passed on options, then we have only one...
120 numberOfConnections = 1;
13 } else {
14 // Get the amount of connections in the pool to ensure we have authenticated all comments
150 numberOfConnections = db.serverConfig.allRawConnections().length;
160 options['onAll'] = true;
17 }
18
19 // Let's start the sasl process
200 var command = {
21 authenticate: 1
22 , mechanism: 'MONGODB-X509'
23 , user: username
24 };
25
26 // Grab all the connections
270 var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections();
28
29 // Authenticate all connections
300 for(var i = 0; i < numberOfConnections; i++) {
310 var connection = connections[i];
32 // Execute first sasl step
330 db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, result) {
34 // Count down
350 numberOfConnections = numberOfConnections - 1;
36
37 // Ensure we save any error
380 if(err) {
390 errorObject = err;
400 } else if(result.documents[0].err != null || result.documents[0].errmsg != null){
410 errorObject = utils.toError(result.documents[0]);
42 }
43
44 // Work around the case where the number of connections are 0
450 if(numberOfConnections <= 0 && typeof callback == 'function') {
460 var internalCallback = callback;
470 callback = null;
48
490 if(errorObject == null && result.documents[0].ok == 1) {
50 // We authenticated correctly save the credentials
510 db.serverConfig.auth.add('MONGODB-X509', db.databaseName, username, password);
52 // Return callback
530 internalCallback(errorObject, true);
54 } else {
550 internalCallback(errorObject, false);
56 }
57 }
58 });
59 }
60}
61
621exports.authenticate = authenticate;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection.js

63%
52
33
19
LineHitsSource
1/**
2 * Module dependencies.
3 * @ignore
4 */
51var InsertCommand = require('./commands/insert_command').InsertCommand
6 , QueryCommand = require('./commands/query_command').QueryCommand
7 , DeleteCommand = require('./commands/delete_command').DeleteCommand
8 , UpdateCommand = require('./commands/update_command').UpdateCommand
9 , DbCommand = require('./commands/db_command').DbCommand
10 , ObjectID = require('bson').ObjectID
11 , Code = require('bson').Code
12 , Cursor = require('./cursor').Cursor
13 , utils = require('./utils')
14 , shared = require('./collection/shared')
15 , core = require('./collection/core')
16 , query = require('./collection/query')
17 , index = require('./collection/index')
18 , geo = require('./collection/geo')
19 , commands = require('./collection/commands')
20 , aggregation = require('./collection/aggregation');
21
22/**
23 * Create a new Collection instance (INTERNAL TYPE, do not instantiate directly)
24 *
25 * Options
26 * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
27 * - **slaveOk** {Boolean, default:false}, Allow reads from secondaries.
28 * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
29 * - **raw** {Boolean, default:false}, perform all operations using raw bson objects.
30 * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
31 *
32 * @class Represents a Collection
33 * @param {Object} db db instance.
34 * @param {String} collectionName collection name.
35 * @param {Object} [pkFactory] alternative primary key factory.
36 * @param {Object} [options] additional options for the collection.
37 * @return {Object} a collection instance.
38 */
391function Collection (db, collectionName, pkFactory, options) {
400 if(!(this instanceof Collection)) return new Collection(db, collectionName, pkFactory, options);
41
420 shared.checkCollectionName(collectionName);
43
440 this.db = db;
450 this.collectionName = collectionName;
460 this.internalHint = null;
470 this.opts = options != null && ('object' === typeof options) ? options : {};
480 this.slaveOk = options == null || options.slaveOk == null ? db.slaveOk : options.slaveOk;
490 this.serializeFunctions = options == null || options.serializeFunctions == null ? db.serializeFunctions : options.serializeFunctions;
500 this.raw = options == null || options.raw == null ? db.raw : options.raw;
51
520 this.readPreference = options == null || options.readPreference == null ? db.serverConfig.options.readPreference : options.readPreference;
530 this.readPreference = this.readPreference == null ? 'primary' : this.readPreference;
54
55
560 this.pkFactory = pkFactory == null
57 ? ObjectID
58 : pkFactory;
59
60 // Server Capabilities
610 this.serverCapabilities = this.db.serverConfig._serverCapabilities;
62}
63
64/**
65 * Inserts a single document or a an array of documents into MongoDB.
66 *
67 * Options
68 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
69 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
70 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
71 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
72 * - **continueOnError/keepGoing** {Boolean, default:false}, keep inserting documents even if one document has an error, *mongodb 1.9.1 >*.
73 * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
74 * - **forceServerObjectId** {Boolean, default:false}, let server assign ObjectId instead of the driver
75 * - **checkKeys** {Boolean, default:true}, allows for disabling of document key checking (WARNING OPENS YOU UP TO INJECTION ATTACKS)
76 *
77 * Deprecated Options
78 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
79 *
80 * @param {Array|Object} docs
81 * @param {Object} [options] optional options for insert command
82 * @param {Function} [callback] optional callback for the function, must be provided when using a writeconcern
83 * @return {null}
84 * @api public
85 */
862Collection.prototype.insert = function() { return core.insert; }();
87
88/**
89 * Removes documents specified by `selector` from the db.
90 *
91 * Options
92 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
93 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
94 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
95 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
96 * - **single** {Boolean, default:false}, removes the first document found.
97 *
98 * Deprecated Options
99 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
100 *
101 * @param {Object} [selector] optional select, no selector is equivalent to removing all documents.
102 * @param {Object} [options] additional options during remove.
103 * @param {Function} [callback] must be provided if you performing a remove with a writeconcern
104 * @return {null}
105 * @api public
106 */
1072Collection.prototype.remove = function() { return core.remove; }();
108
109/**
110 * Renames the collection.
111 *
112 * Options
113 * - **dropTarget** {Boolean, default:false}, drop the target name collection if it previously exists.
114 *
115 * @param {String} newName the new name of the collection.
116 * @param {Object} [options] returns option results.
117 * @param {Function} callback the callback accepting the result
118 * @return {null}
119 * @api public
120 */
1212Collection.prototype.rename = function() { return commands.rename; }();
122
123/**
124 * Save a document. Simple full document replacement function. Not recommended for efficiency, use atomic
125 * operators and update instead for more efficient operations.
126 *
127 * Options
128 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
129 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
130 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
131 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
132 *
133 * Deprecated Options
134 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
135 *
136 * @param {Object} [doc] the document to save
137 * @param {Object} [options] additional options during remove.
138 * @param {Function} [callback] must be provided if you performing a safe save
139 * @return {null}
140 * @api public
141 */
1422Collection.prototype.save = function() { return core.save; }();
143
144/**
145 * Updates documents.
146 *
147 * Options
148 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
149 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
150 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
151 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
152 * - **upsert** {Boolean, default:false}, perform an upsert operation.
153 * - **multi** {Boolean, default:false}, update all documents matching the selector.
154 * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
155 * - **checkKeys** {Boolean, default:true}, allows for disabling of document key checking (WARNING OPENS YOU UP TO INJECTION ATTACKS)
156 *
157 * Deprecated Options
158 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
159 *
160 * @param {Object} selector the query to select the document/documents to be updated
161 * @param {Object} document the fields/vals to be updated, or in the case of an upsert operation, inserted.
162 * @param {Object} [options] additional options during update.
163 * @param {Function} [callback] must be provided if you performing an update with a writeconcern
164 * @return {null}
165 * @api public
166 */
1672Collection.prototype.update = function() { return core.update; }();
168
169/**
170 * The distinct command returns returns a list of distinct values for the given key across a collection.
171 *
172 * Options
173 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
174 *
175 * @param {String} key key to run distinct against.
176 * @param {Object} [query] option query to narrow the returned objects.
177 * @param {Object} [options] additional options during update.
178 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from distinct or null if an error occured.
179 * @return {null}
180 * @api public
181 */
1822Collection.prototype.distinct = function() { return commands.distinct; }();
183
184/**
185 * Count number of matching documents in the db to a query.
186 *
187 * Options
188 * - **skip** {Number}, The number of documents to skip for the count.
189 * - **limit** {Number}, The limit of documents to count.
190 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
191 *
192 * @param {Object} [query] query to filter by before performing count.
193 * @param {Object} [options] additional options during count.
194 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the count method or null if an error occured.
195 * @return {null}
196 * @api public
197 */
1982Collection.prototype.count = function() { return commands.count; }();
199
200/**
201 * Drop the collection
202 *
203 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the drop method or null if an error occured.
204 * @return {null}
205 * @api public
206 */
2071Collection.prototype.drop = function drop(callback) {
2080 this.db.dropCollection(this.collectionName, callback);
209};
210
211/**
212 * Find and update a document.
213 *
214 * Options
215 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
216 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
217 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
218 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
219 * - **remove** {Boolean, default:false}, set to true to remove the object before returning.
220 * - **upsert** {Boolean, default:false}, perform an upsert operation.
221 * - **new** {Boolean, default:false}, set to true if you want to return the modified object rather than the original. Ignored for remove.
222 *
223 * Deprecated Options
224 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
225 *
226 * @param {Object} query query object to locate the object to modify
227 * @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate
228 * @param {Object} doc - the fields/vals to be updated
229 * @param {Object} [options] additional options during update.
230 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndModify method or null if an error occured.
231 * @return {null}
232 * @api public
233 */
2342Collection.prototype.findAndModify = function() { return core.findAndModify; }();
235
236/**
237 * Find and remove a document
238 *
239 * Options
240 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
241 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
242 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
243 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
244 *
245 * Deprecated Options
246 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
247 *
248 * @param {Object} query query object to locate the object to modify
249 * @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate
250 * @param {Object} [options] additional options during update.
251 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndRemove method or null if an error occured.
252 * @return {null}
253 * @api public
254 */
2552Collection.prototype.findAndRemove = function() { return core.findAndRemove; }();
256
257/**
258 * Creates a cursor for a query that can be used to iterate over results from MongoDB
259 *
260 * Various argument possibilities
261 * - callback?
262 * - selector, callback?,
263 * - selector, fields, callback?
264 * - selector, options, callback?
265 * - selector, fields, options, callback?
266 * - selector, fields, skip, limit, callback?
267 * - selector, fields, skip, limit, timeout, callback?
268 *
269 * Options
270 * - **limit** {Number, default:0}, sets the limit of documents returned in the query.
271 * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc.
272 * - **fields** {Object}, the fields to return in the query. Object of fields to include or exclude (not both), {'a':1}
273 * - **skip** {Number, default:0}, set to skip N documents ahead in your query (useful for pagination).
274 * - **hint** {Object}, tell the query to use specific indexes in the query. Object of indexes to use, {'_id':1}
275 * - **explain** {Boolean, default:false}, explain the query instead of returning the data.
276 * - **snapshot** {Boolean, default:false}, snapshot query.
277 * - **timeout** {Boolean, default:false}, specify if the cursor can timeout.
278 * - **tailable** {Boolean, default:false}, specify if the cursor is tailable.
279 * - **tailableRetryInterval** {Number, default:100}, specify the miliseconds between getMores on tailable cursor.
280 * - **numberOfRetries** {Number, default:5}, specify the number of times to retry the tailable cursor.
281 * - **awaitdata** {Boolean, default:false} allow the cursor to wait for data, only applicable for tailable cursor.
282 * - **oplogReplay** {Boolean, default:false} sets an internal flag, only applicable for tailable cursor.
283 * - **exhaust** {Boolean, default:false} have the server send all the documents at once as getMore packets, not recommended.
284 * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results.
285 * - **returnKey** {Boolean, default:false}, only return the index key.
286 * - **maxScan** {Number}, Limit the number of items to scan.
287 * - **min** {Number}, Set index bounds.
288 * - **max** {Number}, Set index bounds.
289 * - **showDiskLoc** {Boolean, default:false}, Show disk location of results.
290 * - **comment** {String}, You can put a $comment field on a query to make looking in the profiler logs simpler.
291 * - **raw** {Boolean, default:false}, Return all BSON documents as Raw Buffer documents.
292 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
293 * - **numberOfRetries** {Number, default:5}, if using awaidata specifies the number of times to retry on timeout.
294 * - **partial** {Boolean, default:false}, specify if the cursor should return partial results when querying against a sharded system
295 *
296 * @param {Object|ObjectID} query query object to locate the object to modify
297 * @param {Object} [options] additional options during update.
298 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the find method or null if an error occured.
299 * @return {Cursor} returns a cursor to the query
300 * @api public
301 */
3022Collection.prototype.find = function() { return query.find; }();
303
304/**
305 * Finds a single document based on the query
306 *
307 * Various argument possibilities
308 * - callback?
309 * - selector, callback?,
310 * - selector, fields, callback?
311 * - selector, options, callback?
312 * - selector, fields, options, callback?
313 * - selector, fields, skip, limit, callback?
314 * - selector, fields, skip, limit, timeout, callback?
315 *
316 * Options
317 * - **limit** {Number, default:0}, sets the limit of documents returned in the query.
318 * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc.
319 * - **fields** {Object}, the fields to return in the query. Object of fields to include or exclude (not both), {'a':1}
320 * - **skip** {Number, default:0}, set to skip N documents ahead in your query (useful for pagination).
321 * - **hint** {Object}, tell the query to use specific indexes in the query. Object of indexes to use, {'_id':1}
322 * - **explain** {Boolean, default:false}, explain the query instead of returning the data.
323 * - **snapshot** {Boolean, default:false}, snapshot query.
324 * - **timeout** {Boolean, default:false}, specify if the cursor can timeout.
325 * - **tailable** {Boolean, default:false}, specify if the cursor is tailable.
326 * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results.
327 * - **returnKey** {Boolean, default:false}, only return the index key.
328 * - **maxScan** {Number}, Limit the number of items to scan.
329 * - **min** {Number}, Set index bounds.
330 * - **max** {Number}, Set index bounds.
331 * - **showDiskLoc** {Boolean, default:false}, Show disk location of results.
332 * - **comment** {String}, You can put a $comment field on a query to make looking in the profiler logs simpler.
333 * - **raw** {Boolean, default:false}, Return all BSON documents as Raw Buffer documents.
334 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
335 * - **partial** {Boolean, default:false}, specify if the cursor should return partial results when querying against a sharded system
336 *
337 * @param {Object|ObjectID} query query object to locate the object to modify
338 * @param {Object} [options] additional options during update.
339 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findOne method or null if an error occured.
340 * @return {Cursor} returns a cursor to the query
341 * @api public
342 */
3432Collection.prototype.findOne = function() { return query.findOne; }();
344
345/**
346 * Creates an index on the collection.
347 *
348 * Options
349 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
350 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
351 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
352 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
353 * - **unique** {Boolean, default:false}, creates an unique index.
354 * - **sparse** {Boolean, default:false}, creates a sparse index.
355 * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible.
356 * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value
357 * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates.
358 * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates.
359 * - **v** {Number}, specify the format version of the indexes.
360 * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
361 * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
362 *
363 * Deprecated Options
364 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
365 *
366 * @param {Object} fieldOrSpec fieldOrSpec that defines the index.
367 * @param {Object} [options] additional options during update.
368 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the createIndex method or null if an error occured.
369 * @return {null}
370 * @api public
371 */
3722Collection.prototype.createIndex = function() { return index.createIndex; }();
373
374/**
375 * Ensures that an index exists, if it does not it creates it
376 *
377 * Options
378 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
379 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
380 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
381 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
382 * - **unique** {Boolean, default:false}, creates an unique index.
383 * - **sparse** {Boolean, default:false}, creates a sparse index.
384 * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible.
385 * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value
386 * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates.
387 * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates.
388 * - **v** {Number}, specify the format version of the indexes.
389 * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
390 * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
391 *
392 * Deprecated Options
393 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
394 *
395 * @param {Object} fieldOrSpec fieldOrSpec that defines the index.
396 * @param {Object} [options] additional options during update.
397 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the ensureIndex method or null if an error occured.
398 * @return {null}
399 * @api public
400 */
4012Collection.prototype.ensureIndex = function() { return index.ensureIndex; }();
402
403/**
404 * Retrieves this collections index info.
405 *
406 * Options
407 * - **full** {Boolean, default:false}, returns the full raw index information.
408 *
409 * @param {Object} [options] additional options during update.
410 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexInformation method or null if an error occured.
411 * @return {null}
412 * @api public
413 */
4142Collection.prototype.indexInformation = function() { return index.indexInformation; }();
415
416/**
417 * Drops an index from this collection.
418 *
419 * @param {String} name
420 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndex method or null if an error occured.
421 * @return {null}
422 * @api public
423 */
4241Collection.prototype.dropIndex = function dropIndex (name, callback) {
4250 this.db.dropIndex(this.collectionName, name, callback);
426};
427
428/**
429 * Drops all indexes from this collection.
430 *
431 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropAllIndexes method or null if an error occured.
432 * @return {null}
433 * @api public
434 */
4352Collection.prototype.dropAllIndexes = function() { return index.dropAllIndexes; }();
436
437/**
438 * Drops all indexes from this collection.
439 *
440 * @deprecated
441 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndexes method or null if an error occured.
442 * @return {null}
443 * @api private
444 */
4452Collection.prototype.dropIndexes = function() { return Collection.prototype.dropAllIndexes; }();
446
447/**
448 * Reindex all indexes on the collection
449 * Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections.
450 *
451 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the reIndex method or null if an error occured.
452 * @return {null}
453 * @api public
454**/
4551Collection.prototype.reIndex = function(callback) {
4560 this.db.reIndex(this.collectionName, callback);
457}
458
459/**
460 * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection.
461 *
462 * Options
463 * - **out** {Object}, sets the output target for the map reduce job. *{inline:1} | {replace:'collectionName'} | {merge:'collectionName'} | {reduce:'collectionName'}*
464 * - **query** {Object}, query filter object.
465 * - **sort** {Object}, sorts the input objects using this key. Useful for optimization, like sorting by the emit key for fewer reduces.
466 * - **limit** {Number}, number of objects to return from collection.
467 * - **keeptemp** {Boolean, default:false}, keep temporary data.
468 * - **finalize** {Function | String}, finalize function.
469 * - **scope** {Object}, can pass in variables that can be access from map/reduce/finalize.
470 * - **jsMode** {Boolean, default:false}, it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X.
471 * - **verbose** {Boolean, default:false}, provide statistics on job execution time.
472 * - **readPreference** {String, only for inline results}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
473 *
474 * @param {Function|String} map the mapping function.
475 * @param {Function|String} reduce the reduce function.
476 * @param {Objects} [options] options for the map reduce job.
477 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the mapReduce method or null if an error occured.
478 * @return {null}
479 * @api public
480 */
4812Collection.prototype.mapReduce = function() { return aggregation.mapReduce; }();
482
483/**
484 * Run a group command across a collection
485 *
486 * Options
487 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
488 *
489 * @param {Object|Array|Function|Code} keys an object, array or function expressing the keys to group by.
490 * @param {Object} condition an optional condition that must be true for a row to be considered.
491 * @param {Object} initial initial value of the aggregation counter object.
492 * @param {Function|Code} reduce the reduce function aggregates (reduces) the objects iterated
493 * @param {Function|Code} finalize an optional function to be run on each item in the result set just before the item is returned.
494 * @param {Boolean} command specify if you wish to run using the internal group command or using eval, default is true.
495 * @param {Object} [options] additional options during update.
496 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the group method or null if an error occured.
497 * @return {null}
498 * @api public
499 */
5002Collection.prototype.group = function() { return aggregation.group; }();
501
502/**
503 * Returns the options of the collection.
504 *
505 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the options method or null if an error occured.
506 * @return {null}
507 * @api public
508 */
5092Collection.prototype.options = function() { return commands.options; }();
510
511/**
512 * Returns if the collection is a capped collection
513 *
514 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the isCapped method or null if an error occured.
515 * @return {null}
516 * @api public
517 */
5182Collection.prototype.isCapped = function() { return commands.isCapped; }();
519
520/**
521 * Checks if one or more indexes exist on the collection
522 *
523 * @param {String|Array} indexNames check if one or more indexes exist on the collection.
524 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexExists method or null if an error occured.
525 * @return {null}
526 * @api public
527 */
5282Collection.prototype.indexExists = function() { return index.indexExists; }();
529
530/**
531 * Execute the geoNear command to search for items in the collection
532 *
533 * Options
534 * - **num** {Number}, max number of results to return.
535 * - **maxDistance** {Number}, include results up to maxDistance from the point.
536 * - **distanceMultiplier** {Number}, include a value to multiply the distances with allowing for range conversions.
537 * - **query** {Object}, filter the results by a query.
538 * - **spherical** {Boolean, default:false}, perform query using a spherical model.
539 * - **uniqueDocs** {Boolean, default:false}, the closest location in a document to the center of the search region will always be returned MongoDB > 2.X.
540 * - **includeLocs** {Boolean, default:false}, include the location data fields in the top level of the results MongoDB > 2.X.
541 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
542 *
543 * @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order.
544 * @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order.
545 * @param {Objects} [options] options for the map reduce job.
546 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoNear method or null if an error occured.
547 * @return {null}
548 * @api public
549 */
5502Collection.prototype.geoNear = function() { return geo.geoNear; }();
551
552/**
553 * Execute a geo search using a geo haystack index on a collection.
554 *
555 * Options
556 * - **maxDistance** {Number}, include results up to maxDistance from the point.
557 * - **search** {Object}, filter the results by a query.
558 * - **limit** {Number}, max number of results to return.
559 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
560 *
561 * @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order.
562 * @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order.
563 * @param {Objects} [options] options for the map reduce job.
564 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoHaystackSearch method or null if an error occured.
565 * @return {null}
566 * @api public
567 */
5682Collection.prototype.geoHaystackSearch = function() { return geo.geoHaystackSearch; }();
569
570/**
571 * Retrieve all the indexes on the collection.
572 *
573 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexes method or null if an error occured.
574 * @return {null}
575 * @api public
576 */
5771Collection.prototype.indexes = function indexes(callback) {
5780 this.db.indexInformation(this.collectionName, {full:true}, callback);
579}
580
581/**
582 * Execute an aggregation framework pipeline against the collection, needs MongoDB >= 2.2
583 *
584 * Options
585 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
586 *
587 * @param {Array} array containing all the aggregation framework commands for the execution.
588 * @param {Object} [options] additional options during update.
589 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the aggregate method or null if an error occured.
590 * @return {null}
591 * @api public
592 */
5932Collection.prototype.aggregate = function() { return aggregation.aggregate; }();
594
595/**
596 * Get all the collection statistics.
597 *
598 * Options
599 * - **scale** {Number}, divide the returned sizes by scale value.
600 * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
601 *
602 * @param {Objects} [options] options for the stats command.
603 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the stats method or null if an error occured.
604 * @return {null}
605 * @api public
606 */
6072Collection.prototype.stats = function() { return commands.stats; }();
608
609/**
610 * @ignore
611 */
6121Object.defineProperty(Collection.prototype, "hint", {
613 enumerable: true
614 , get: function () {
6150 return this.internalHint;
616 }
617 , set: function (v) {
6180 this.internalHint = shared.normalizeHintField(v);
619 }
620});
621
622/**
623 * Expose.
624 */
6251exports.Collection = Collection;
626

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection/aggregation.js

7%
150
11
139
LineHitsSource
11var shared = require('./shared')
2 , utils = require('../utils')
3 , AggregationCursor = require('../aggregation_cursor').AggregationCursor
4 , Code = require('bson').Code
5 , DbCommand = require('../commands/db_command').DbCommand;
6
7/**
8 * Functions that are passed as scope args must
9 * be converted to Code instances.
10 * @ignore
11 */
121function processScope (scope) {
130 if (!utils.isObject(scope)) {
140 return scope;
15 }
16
170 var keys = Object.keys(scope);
180 var i = keys.length;
190 var key;
20
210 while (i--) {
220 key = keys[i];
230 if ('function' == typeof scope[key]) {
240 scope[key] = new Code(String(scope[key]));
25 } else {
260 scope[key] = processScope(scope[key]);
27 }
28 }
29
300 return scope;
31}
32
331var pipe = function() {
340 return new AggregationCursor(this, this.serverCapabilities);
35}
36
371var mapReduce = function mapReduce (map, reduce, options, callback) {
380 if ('function' === typeof options) callback = options, options = {};
39 // Out must allways be defined (make sure we don't break weirdly on pre 1.8+ servers)
400 if(null == options.out) {
410 throw new Error("the out option parameter must be defined, see mongodb docs for possible values");
42 }
43
440 if ('function' === typeof map) {
450 map = map.toString();
46 }
47
480 if ('function' === typeof reduce) {
490 reduce = reduce.toString();
50 }
51
520 if ('function' === typeof options.finalize) {
530 options.finalize = options.finalize.toString();
54 }
55
560 var mapCommandHash = {
57 mapreduce: this.collectionName
58 , map: map
59 , reduce: reduce
60 };
61
62 // Add any other options passed in
630 for (var name in options) {
640 if ('scope' == name) {
650 mapCommandHash[name] = processScope(options[name]);
66 } else {
670 mapCommandHash[name] = options[name];
68 }
69 }
70
71 // Set read preference if we set one
720 var readPreference = shared._getReadConcern(this, options);
73
74 // If we have a read preference and inline is not set as output fail hard
750 if((readPreference != false && readPreference != 'primary')
76 && options['out'] && (options['out'].inline != 1 && options['out'] != 'inline')) {
770 readPreference = 'primary';
78 }
79
80 // self
810 var self = this;
820 var cmd = DbCommand.createDbCommand(this.db, mapCommandHash);
83
840 this.db._executeQueryCommand(cmd, {read:readPreference}, function (err, result) {
850 if(err) return callback(err);
860 if(!result || !result.documents || result.documents.length == 0)
870 return callback(Error("command failed to return results"), null)
88
89 // Check if we have an error
900 if(1 != result.documents[0].ok || result.documents[0].err || result.documents[0].errmsg) {
910 return callback(utils.toError(result.documents[0]));
92 }
93
94 // Create statistics value
950 var stats = {};
960 if(result.documents[0].timeMillis) stats['processtime'] = result.documents[0].timeMillis;
970 if(result.documents[0].counts) stats['counts'] = result.documents[0].counts;
980 if(result.documents[0].timing) stats['timing'] = result.documents[0].timing;
99
100 // invoked with inline?
1010 if(result.documents[0].results) {
102 // If we wish for no verbosity
1030 if(options['verbose'] == null || !options['verbose']) {
1040 return callback(null, result.documents[0].results);
105 }
1060 return callback(null, result.documents[0].results, stats);
107 }
108
109 // The returned collection
1100 var collection = null;
111
112 // If we have an object it's a different db
1130 if(result.documents[0].result != null && typeof result.documents[0].result == 'object') {
1140 var doc = result.documents[0].result;
1150 collection = self.db.db(doc.db).collection(doc.collection);
116 } else {
117 // Create a collection object that wraps the result collection
1180 collection = self.db.collection(result.documents[0].result)
119 }
120
121 // If we wish for no verbosity
1220 if(options['verbose'] == null || !options['verbose']) {
1230 return callback(err, collection);
124 }
125
126 // Return stats as third set of values
1270 callback(err, collection, stats);
128 });
129};
130
131/**
132 * Group function helper
133 * @ignore
134 */
1351var groupFunction = function () {
1360 var c = db[ns].find(condition);
1370 var map = new Map();
1380 var reduce_function = reduce;
139
1400 while (c.hasNext()) {
1410 var obj = c.next();
1420 var key = {};
143
1440 for (var i = 0, len = keys.length; i < len; ++i) {
1450 var k = keys[i];
1460 key[k] = obj[k];
147 }
148
1490 var aggObj = map.get(key);
150
1510 if (aggObj == null) {
1520 var newObj = Object.extend({}, key);
1530 aggObj = Object.extend(newObj, initial);
1540 map.put(key, aggObj);
155 }
156
1570 reduce_function(obj, aggObj);
158 }
159
1600 return { "result": map.values() };
161}.toString();
162
1631var group = function group(keys, condition, initial, reduce, finalize, command, options, callback) {
1640 var args = Array.prototype.slice.call(arguments, 3);
1650 callback = args.pop();
166 // Fetch all commands
1670 reduce = args.length ? args.shift() : null;
1680 finalize = args.length ? args.shift() : null;
1690 command = args.length ? args.shift() : null;
1700 options = args.length ? args.shift() || {} : {};
171
172 // Make sure we are backward compatible
1730 if(!(typeof finalize == 'function')) {
1740 command = finalize;
1750 finalize = null;
176 }
177
1780 if (!Array.isArray(keys) && keys instanceof Object && typeof(keys) !== 'function' && !(keys instanceof Code)) {
1790 keys = Object.keys(keys);
180 }
181
1820 if(typeof reduce === 'function') {
1830 reduce = reduce.toString();
184 }
185
1860 if(typeof finalize === 'function') {
1870 finalize = finalize.toString();
188 }
189
190 // Set up the command as default
1910 command = command == null ? true : command;
192
193 // Execute using the command
1940 if(command) {
1950 var reduceFunction = reduce instanceof Code
196 ? reduce
197 : new Code(reduce);
198
1990 var selector = {
200 group: {
201 'ns': this.collectionName
202 , '$reduce': reduceFunction
203 , 'cond': condition
204 , 'initial': initial
205 , 'out': "inline"
206 }
207 };
208
209 // if finalize is defined
2100 if(finalize != null) selector.group['finalize'] = finalize;
211 // Set up group selector
2120 if ('function' === typeof keys || keys instanceof Code) {
2130 selector.group.$keyf = keys instanceof Code
214 ? keys
215 : new Code(keys);
216 } else {
2170 var hash = {};
2180 keys.forEach(function (key) {
2190 hash[key] = 1;
220 });
2210 selector.group.key = hash;
222 }
223
2240 var cmd = DbCommand.createDbSlaveOkCommand(this.db, selector);
225 // Set read preference if we set one
2260 var readPreference = shared._getReadConcern(this, options);
227 // Execute the command
2280 this.db._executeQueryCommand(cmd
229 , {read:readPreference}
230 , utils.handleSingleCommandResultReturn(null, null, function(err, result) {
2310 if(err) return callback(err, null);
2320 callback(null, result.retval);
233 }));
234 } else {
235 // Create execution scope
2360 var scope = reduce != null && reduce instanceof Code
237 ? reduce.scope
238 : {};
239
2400 scope.ns = this.collectionName;
2410 scope.keys = keys;
2420 scope.condition = condition;
2430 scope.initial = initial;
244
245 // Pass in the function text to execute within mongodb.
2460 var groupfn = groupFunction.replace(/ reduce;/, reduce.toString() + ';');
247
2480 this.db.eval(new Code(groupfn, scope), function (err, results) {
2490 if (err) return callback(err, null);
2500 callback(null, results.result || results);
251 });
252 }
253};
254
2551var aggregate = function(pipeline, options, callback) {
2560 var args = Array.prototype.slice.call(arguments, 0);
2570 callback = args.pop();
2580 var self = this;
259
260 // If we have any of the supported options in the options object
2610 var opts = args[args.length - 1];
2620 options = opts.readPreference
263 || opts.explain
264 || opts.cursor
265 || opts.out
266 || opts.allowDiskUsage ? args.pop() : {}
267 // If the callback is the option (as for cursor override it)
2680 if(typeof callback == 'object' && callback != null) options = callback;
269
270 // Convert operations to an array
2710 if(!Array.isArray(args[0])) {
2720 pipeline = [];
273 // Push all the operations to the pipeline
2740 for(var i = 0; i < args.length; i++) pipeline.push(args[i]);
275 }
276
277 // Is the user requesting a cursor
2780 if(options.cursor != null && options.out == null) {
279 // Set the aggregation cursor options
2800 var agg_cursor_options = options.cursor;
2810 agg_cursor_options.pipe = pipeline;
2820 agg_cursor_options.allowDiskUsage = options.allowDiskUsage == null ? false : options.allowDiskUsage;
283 // Return the aggregation cursor
2840 return new AggregationCursor(this, this.serverCapabilities, agg_cursor_options);
285 }
286
287 // If out was specified
2880 if(typeof options.out == 'string') {
2890 pipeline.push({$out: options.out});
290 }
291
292 // Build the command
2930 var command = { aggregate : this.collectionName, pipeline : pipeline};
294 // If we have allowDiskUsage defined
2950 if(options.allowDiskUsage) command.allowDiskUsage = options.allowDiskUsage;
296
297 // Ensure we have the right read preference inheritance
2980 options.readPreference = shared._getReadConcern(this, options);
299 // If explain has been specified add it
3000 if(options.explain) command.explain = options.explain;
301 // Execute the command
3020 this.db.command(command, options, function(err, result) {
3030 if(err) {
3040 callback(err);
3050 } else if(result['err'] || result['errmsg']) {
3060 callback(utils.toError(result));
3070 } else if(typeof result == 'object' && result['serverPipeline']) {
3080 callback(null, result['serverPipeline']);
3090 } else if(typeof result == 'object' && result['stages']) {
3100 callback(null, result['stages']);
311 } else {
3120 callback(null, result.result);
313 }
314 });
315}
316
3171exports.mapReduce = mapReduce;
3181exports.group = group;
3191exports.aggregate = aggregate;
3201exports.pipe = pipe;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection/commands.js

18%
71
13
58
LineHitsSource
11var shared = require('./shared')
2 , utils = require('../utils')
3 , DbCommand = require('../commands/db_command').DbCommand;
4
51var stats = function stats(options, callback) {
60 var args = Array.prototype.slice.call(arguments, 0);
70 callback = args.pop();
8 // Fetch all commands
90 options = args.length ? args.shift() || {} : {};
10
11 // Build command object
120 var commandObject = {
13 collStats:this.collectionName,
14 }
15
16 // Check if we have the scale value
170 if(options['scale'] != null) commandObject['scale'] = options['scale'];
18
19 // Ensure we have the right read preference inheritance
200 options.readPreference = shared._getReadConcern(this, options);
21
22 // Execute the command
230 this.db.command(commandObject, options, callback);
24}
25
261var count = function count(query, options, callback) {
270 var args = Array.prototype.slice.call(arguments, 0);
280 callback = args.pop();
290 query = args.length ? args.shift() || {} : {};
300 options = args.length ? args.shift() || {} : {};
310 var skip = options.skip;
320 var limit = options.limit;
330 var maxTimeMS = options.maxTimeMS;
34
35 // Final query
360 var commandObject = {
37 'count': this.collectionName
38 , 'query': query
39 , 'fields': null
40 };
41
42 // Add limit and skip if defined
430 if(typeof skip == 'number') commandObject.skip = skip;
440 if(typeof limit == 'number') commandObject.limit = limit;
450 if(typeof maxTimeMS == 'number') commandObject['$maxTimeMS'] = maxTimeMS;
46
47 // Set read preference if we set one
480 var readPreference = shared._getReadConcern(this, options);
49 // Execute the command
500 this.db._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this.db, commandObject)
51 , {read: readPreference}
52 , utils.handleSingleCommandResultReturn(null, null, function(err, result) {
530 if(err) return callback(err, null);
540 if(result == null) return callback(new Error("no result returned for count"), null);
550 callback(null, result.n);
56 }));
57};
58
591var distinct = function distinct(key, query, options, callback) {
600 var args = Array.prototype.slice.call(arguments, 1);
610 callback = args.pop();
620 query = args.length ? args.shift() || {} : {};
630 options = args.length ? args.shift() || {} : {};
64
650 var mapCommandHash = {
66 'distinct': this.collectionName
67 , 'query': query
68 , 'key': key
69 };
70
71 // Set read preference if we set one
720 var readPreference = options['readPreference'] ? options['readPreference'] : false;
73 // Create the command
740 var cmd = DbCommand.createDbSlaveOkCommand(this.db, mapCommandHash);
75
760 this.db._executeQueryCommand(cmd, {read:readPreference}, function (err, result) {
770 if(err)
780 return callback(err);
790 if(result.documents[0].ok != 1)
800 return callback(new Error(result.documents[0].errmsg));
810 callback(null, result.documents[0].values);
82 });
83};
84
851var rename = function rename (newName, options, callback) {
860 var self = this;
870 if(typeof options == 'function') {
880 callback = options;
890 options = {}
90 }
91
92 // Get collection class
930 var Collection = require('../collection').Collection;
94 // Ensure the new name is valid
950 shared.checkCollectionName(newName);
96
97 // Execute the command, return the new renamed collection if successful
980 self.db._executeQueryCommand(DbCommand.createRenameCollectionCommand(self.db, self.collectionName, newName, options)
99 , utils.handleSingleCommandResultReturn(true, false, function(err, result) {
1000 if(err) return callback(err, null)
1010 try {
1020 if(options.new_collection)
1030 return callback(null, new Collection(self.db, newName, self.db.pkFactory));
1040 self.collectionName = newName;
1050 callback(null, self);
106 } catch(err) {
1070 callback(err, null);
108 }
109 }));
110};
111
1121var options = function options(callback) {
1130 this.db.collectionsInfo(this.collectionName, function (err, cursor) {
1140 if (err) return callback(err);
1150 cursor.nextObject(function (err, document) {
1160 callback(err, document && document.options || null);
117 });
118 });
119};
120
1211var isCapped = function isCapped(callback) {
1220 this.options(function(err, document) {
1230 if(err != null) {
1240 callback(err);
125 } else {
1260 callback(null, document && document.capped);
127 }
128 });
129};
130
1311exports.stats = stats;
1321exports.count = count;
1331exports.distinct = distinct;
1341exports.rename = rename;
1351exports.options = options;
1361exports.isCapped = isCapped;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection/core.js

6%
315
19
296
LineHitsSource
11var InsertCommand = require('../commands/insert_command').InsertCommand
2 , DeleteCommand = require('../commands/delete_command').DeleteCommand
3 , UpdateCommand = require('../commands/update_command').UpdateCommand
4 , DbCommand = require('../commands/db_command').DbCommand
5 , utils = require('../utils')
6 , hasWriteCommands = require('../utils').hasWriteCommands
7 , shared = require('./shared');
8
9/**
10 * Precompiled regexes
11 * @ignore
12 **/
131var eErrorMessages = /No matching object found/;
14
15// ***************************************************
16// Insert function
17// ***************************************************
181var insert = function insert (docs, options, callback) {
190 if ('function' === typeof options) callback = options, options = {};
200 if(options == null) options = {};
210 if(!('function' === typeof callback)) callback = null;
22
23 // Get a connection
240 var connection = this.db.serverConfig.checkoutWriter();
250 var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true;
26 // If we support write commands let's perform the insert using it
270 if(!useLegacyOps && hasWriteCommands(connection)
28 && !Buffer.isBuffer(docs)
29 && (!Array.isArray(docs) && docs.length > 0 && !Buffer.isBuffer(docs[0]))) {
300 insertWithWriteCommands(this, Array.isArray(docs) ? docs : [docs], options, callback);
310 return this
32 }
33
34 // Backwards compatibility
350 insertAll(this, Array.isArray(docs) ? docs : [docs], options, callback);
360 return this;
37};
38
39//
40// Uses the new write commands available from 2.6 >
41//
421var insertWithWriteCommands = function(self, docs, options, callback) {
43 // Get the intended namespace for the operation
440 var namespace = self.collectionName;
45
46 // Ensure we have no \x00 bytes in the name causing wrong parsing
470 if(!!~namespace.indexOf("\x00")) {
480 return callback(new Error("namespace cannot contain a null character"), null);
49 }
50
51 // Check if we have passed in continue on error
520 var continueOnError = typeof options['keepGoing'] == 'boolean'
53 ? options['keepGoing'] : false;
540 continueOnError = typeof options['continueOnError'] == 'boolean'
55 ? options['continueOnError'] : continueOnError;
56
57 // Do we serialzie functions
580 var serializeFunctions = typeof options.serializeFunctions != 'boolean'
59 ? self.serializeFunctions : options.serializeFunctions;
60
61 // Checkout a write connection
620 var connection = self.db.serverConfig.checkoutWriter();
63
64 // Collect errorOptions
650 var errorOptions = shared._getWriteConcern(self, options);
66
67 // If we have a write command with no callback and w:0 fail
680 if(errorOptions.w && errorOptions.w != 0 && callback == null) {
690 throw new Error("writeConcern requires callback")
70 }
71
72 // Add the documents and decorate them with id's if they have none
730 for(var index = 0, len = docs.length; index < len; ++index) {
740 var doc = docs[index];
75
76 // Add id to each document if it's not already defined
770 if (!(Buffer.isBuffer(doc))
78 && doc['_id'] == null
79 && self.db.forceServerObjectId != true
80 && options.forceServerObjectId != true) {
810 doc['_id'] = self.pkFactory.createPk();
82 }
83 }
84
85 // Create the write command
860 var write_command = {
87 insert: namespace
88 , writeConcern: errorOptions
89 , ordered: !continueOnError
90 , documents: docs
91 }
92
93 // Execute the write command
940 self.db.command(write_command
95 , { connection:connection
96 , checkKeys: true
97 , serializeFunctions: serializeFunctions
98 , writeCommand: true }
99 , function(err, result) {
1000 if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null);
1010 if(errorOptions.w == 0) return;
1020 if(callback == null) return;
1030 if(err != null) {
104 // Rewrite for backward compatibility
1050 if(Array.isArray(err.errDetails)) err.code = err.errDetails[0].errCode;
106 // Return the error
1070 return callback(err, null);
108 }
109
110 // Result has an error
1110 if(!result.ok && (result.err != null || result.errmsg != null)) {
112 // Map the error
1130 var error = utils.toError(result);
114 // Backwards compatibility mapping
1150 if(Array.isArray(error.errDetails)) error.code = error.errDetails[0].errCode;
116 // Return the error
1170 return callback(error, null);
118 }
119
120 // Return the results for a whole batch
1210 callback(null, docs)
122 });
123}
124
125//
126// Uses pre 2.6 OP_INSERT wire protocol
127//
1281var insertAll = function insertAll (self, docs, options, callback) {
1290 if('function' === typeof options) callback = options, options = {};
1300 if(options == null) options = {};
1310 if(!('function' === typeof callback)) callback = null;
132
133 // Insert options (flags for insert)
1340 var insertFlags = {};
135 // If we have a mongodb version >= 1.9.1 support keepGoing attribute
1360 if(options['keepGoing'] != null) {
1370 insertFlags['keepGoing'] = options['keepGoing'];
138 }
139
140 // If we have a mongodb version >= 1.9.1 support keepGoing attribute
1410 if(options['continueOnError'] != null) {
1420 insertFlags['continueOnError'] = options['continueOnError'];
143 }
144
145 // DbName
1460 var dbName = options['dbName'];
147 // If no dbname defined use the db one
1480 if(dbName == null) {
1490 dbName = self.db.databaseName;
150 }
151
152 // Either use override on the function, or go back to default on either the collection
153 // level or db
1540 if(options['serializeFunctions'] != null) {
1550 insertFlags['serializeFunctions'] = options['serializeFunctions'];
156 } else {
1570 insertFlags['serializeFunctions'] = self.serializeFunctions;
158 }
159
160 // Get checkKeys value
1610 var checkKeys = typeof options.checkKeys != 'boolean' ? true : options.checkKeys;
162
163 // Pass in options
1640 var insertCommand = new InsertCommand(
165 self.db
166 , dbName + "." + self.collectionName, checkKeys, insertFlags);
167
168 // Add the documents and decorate them with id's if they have none
1690 for(var index = 0, len = docs.length; index < len; ++index) {
1700 var doc = docs[index];
171
172 // Add id to each document if it's not already defined
1730 if (!(Buffer.isBuffer(doc))
174 && doc['_id'] == null
175 && self.db.forceServerObjectId != true
176 && options.forceServerObjectId != true) {
1770 doc['_id'] = self.pkFactory.createPk();
178 }
179
1800 insertCommand.add(doc);
181 }
182
183 // Collect errorOptions
1840 var errorOptions = shared._getWriteConcern(self, options);
185 // Default command options
1860 var commandOptions = {};
187 // If safe is defined check for error message
1880 if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') {
189 // Insert options
1900 commandOptions['read'] = false;
191 // If we have safe set set async to false
1920 if(errorOptions == null) commandOptions['async'] = true;
193
194 // Set safe option
1950 commandOptions['safe'] = errorOptions;
196 // If we have an error option
1970 if(typeof errorOptions == 'object') {
1980 var keys = Object.keys(errorOptions);
1990 for(var i = 0; i < keys.length; i++) {
2000 commandOptions[keys[i]] = errorOptions[keys[i]];
201 }
202 }
203
204 // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection)
2050 self.db._executeInsertCommand(insertCommand, commandOptions, function (err, error) {
2060 error = error && error.documents;
2070 if(!callback) return;
208
2090 if (err) {
2100 callback(err);
2110 } else if(error[0].err || error[0].errmsg) {
2120 callback(utils.toError(error[0]));
2130 } else if(error[0].jnote || error[0].wnote || error[0].wtimeout) {
2140 callback(utils.toError(error[0]));
215 } else {
2160 callback(null, docs);
217 }
218 });
2190 } else if(shared._hasWriteConcern(errorOptions) && callback == null) {
2200 throw new Error("Cannot use a writeConcern without a provided callback");
221 } else {
222 // Execute the call without a write concern
2230 var result = self.db._executeInsertCommand(insertCommand, commandOptions);
224 // If no callback just return
2250 if(!callback) return;
226 // If error return error
2270 if(result instanceof Error) {
2280 return callback(result);
229 }
230
231 // Otherwise just return
2320 return callback(null, docs);
233 }
234};
235
236// ***************************************************
237// Remove function
238// ***************************************************
2391var removeWithWriteCommands = function(self, selector, options, callback) {
2400 if ('function' === typeof selector) {
2410 callback = selector;
2420 selector = options = {};
2430 } else if ('function' === typeof options) {
2440 callback = options;
2450 options = {};
246 }
247
248 // Get the intended namespace for the operation
2490 var namespace = self.collectionName;
250
251 // Ensure we have no \x00 bytes in the name causing wrong parsing
2520 if(!!~namespace.indexOf("\x00")) {
2530 return callback(new Error("namespace cannot contain a null character"), null);
254 }
255
256 // Set default empty selector if none
2570 selector = selector == null ? {} : selector;
258
259 // Check if we have passed in continue on error
2600 var continueOnError = typeof options['keepGoing'] == 'boolean'
261 ? options['keepGoing'] : false;
2620 continueOnError = typeof options['continueOnError'] == 'boolean'
263 ? options['continueOnError'] : continueOnError;
264
265 // Do we serialzie functions
2660 var serializeFunctions = typeof options.serializeFunctions != 'boolean'
267 ? self.serializeFunctions : options.serializeFunctions;
268
269 // Checkout a write connection
2700 var connection = self.db.serverConfig.checkoutWriter();
271
272 // Figure out the value of top
2730 var limit = options.single == true ? 1 : 0;
2740 var upsert = typeof options.upsert == 'boolean' ? options.upsert : false;
275
276 // Collect errorOptions
2770 var errorOptions = shared._getWriteConcern(self, options);
278
279 // If we have a write command with no callback and w:0 fail
2800 if(errorOptions.w && errorOptions.w != 0 && callback == null) {
2810 throw new Error("writeConcern requires callback")
282 }
283
284 // Create the write command
2850 var write_command = {
286 delete: namespace,
287 writeConcern: errorOptions,
288 ordered: !continueOnError,
289 deletes: [{
290 q : selector,
291 limit: limit
292 }]
293 }
294
295 // Execute the write command
2960 self.db.command(write_command
297 , { connection:connection
298 , checkKeys: true
299 , serializeFunctions: serializeFunctions
300 , writeCommand: true }
301 , function(err, result) {
3020 if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null);
3030 if(errorOptions.w == 0) return;
3040 if(callback == null) return;
3050 if(err != null) {
3060 if(Array.isArray(err.errDetails)) err.code = err.errDetails[0].errCode;
307 // Return the error
3080 return callback(err, null);
309 }
310
311 // Result has an error
3120 if(!result.ok && (result.err != null || result.errmsg != null)) {
313 // Map the error
3140 var error = utils.toError(result);
315 // Backwards compatibility mapping
3160 if(Array.isArray(error.errDetails)) error.code = error.errDetails[0].errCode;
317 // Return the error
3180 return callback(error, null);
319 }
320
321 // Backward compatibility format
3220 var r = backWardsCompatibiltyResults(result, 'remove');
323 // Return the results for a whole batch
3240 callback(null, r.n, r)
325 });
326}
327
3281var remove = function remove(selector, options, callback) {
3290 if('function' === typeof options) callback = options, options = null;
3300 if(options == null) options = {};
3310 if(!('function' === typeof callback)) callback = null;
332 // Get a connection
3330 var connection = this.db.serverConfig.checkoutWriter();
3340 var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true;
335 // If we support write commands let's perform the insert using it
3360 if(!useLegacyOps && hasWriteCommands(connection) && !Buffer.isBuffer(selector)) {
3370 return removeWithWriteCommands(this, selector, options, callback);
338 }
339
3400 if ('function' === typeof selector) {
3410 callback = selector;
3420 selector = options = {};
3430 } else if ('function' === typeof options) {
3440 callback = options;
3450 options = {};
346 }
347
348 // Ensure options
3490 if(options == null) options = {};
3500 if(!('function' === typeof callback)) callback = null;
351 // Ensure we have at least an empty selector
3520 selector = selector == null ? {} : selector;
353 // Set up flags for the command, if we have a single document remove
3540 var flags = 0 | (options.single ? 1 : 0);
355
356 // DbName
3570 var dbName = options['dbName'];
358 // If no dbname defined use the db one
3590 if(dbName == null) {
3600 dbName = this.db.databaseName;
361 }
362
363 // Create a delete command
3640 var deleteCommand = new DeleteCommand(
365 this.db
366 , dbName + "." + this.collectionName
367 , selector
368 , flags);
369
3700 var self = this;
3710 var errorOptions = shared._getWriteConcern(self, options);
372 // Execute the command, do not add a callback as it's async
3730 if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') {
374 // Insert options
3750 var commandOptions = {read:false};
376 // If we have safe set set async to false
3770 if(errorOptions == null) commandOptions['async'] = true;
378 // Set safe option
3790 commandOptions['safe'] = true;
380 // If we have an error option
3810 if(typeof errorOptions == 'object') {
3820 var keys = Object.keys(errorOptions);
3830 for(var i = 0; i < keys.length; i++) {
3840 commandOptions[keys[i]] = errorOptions[keys[i]];
385 }
386 }
387
388 // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection)
3890 this.db._executeRemoveCommand(deleteCommand, commandOptions, function (err, error) {
3900 error = error && error.documents;
3910 if(!callback) return;
392
3930 if(err) {
3940 callback(err);
3950 } else if(error[0].err || error[0].errmsg) {
3960 callback(utils.toError(error[0]));
3970 } else if(error[0].jnote || error[0].wnote || error[0].wtimeout) {
3980 callback(utils.toError(error[0]));
399 } else {
4000 callback(null, error[0].n);
401 }
402 });
4030 } else if(shared._hasWriteConcern(errorOptions) && callback == null) {
4040 throw new Error("Cannot use a writeConcern without a provided callback");
405 } else {
4060 var result = this.db._executeRemoveCommand(deleteCommand);
407 // If no callback just return
4080 if (!callback) return;
409 // If error return error
4100 if (result instanceof Error) {
4110 return callback(result);
412 }
413 // Otherwise just return
4140 return callback();
415 }
416};
417
418// ***************************************************
419// Save function
420// ***************************************************
4211var save = function save(doc, options, callback) {
4220 if('function' === typeof options) callback = options, options = null;
4230 if(options == null) options = {};
4240 if(!('function' === typeof callback)) callback = null;
425 // Throw an error if attempting to perform a bulk operation
4260 if(Array.isArray(doc)) throw new Error("doc parameter must be a single document");
427 // Extract the id, if we have one we need to do a update command
4280 var id = doc['_id'];
4290 var commandOptions = shared._getWriteConcern(this, options);
430
4310 if(id != null) {
4320 commandOptions.upsert = true;
4330 this.update({ _id: id }, doc, commandOptions, callback);
434 } else {
4350 this.insert(doc, commandOptions, callback && function (err, docs) {
4360 if(err) return callback(err, null);
437
4380 if(Array.isArray(docs)) {
4390 callback(err, docs[0]);
440 } else {
4410 callback(err, docs);
442 }
443 });
444 }
445};
446
447// ***************************************************
448// Update document function
449// ***************************************************
4501var updateWithWriteCommands = function(self, selector, document, options, callback) {
4510 if('function' === typeof options) callback = options, options = null;
4520 if(options == null) options = {};
4530 if(!('function' === typeof callback)) callback = null;
454
455 // Get the intended namespace for the operation
4560 var namespace = self.collectionName;
457
458 // Ensure we have no \x00 bytes in the name causing wrong parsing
4590 if(!!~namespace.indexOf("\x00")) {
4600 return callback(new Error("namespace cannot contain a null character"), null);
461 }
462
463 // If we are not providing a selector or document throw
4640 if(selector == null || typeof selector != 'object')
4650 return callback(new Error("selector must be a valid JavaScript object"));
4660 if(document == null || typeof document != 'object')
4670 return callback(new Error("document must be a valid JavaScript object"));
468
469 // Check if we have passed in continue on error
4700 var continueOnError = typeof options['keepGoing'] == 'boolean'
471 ? options['keepGoing'] : false;
4720 continueOnError = typeof options['continueOnError'] == 'boolean'
473 ? options['continueOnError'] : continueOnError;
474
475 // Do we serialzie functions
4760 var serializeFunctions = typeof options.serializeFunctions != 'boolean'
477 ? self.serializeFunctions : options.serializeFunctions;
478
479 // Checkout a write connection
4800 var connection = self.db.serverConfig.checkoutWriter();
481
482 // Figure out the value of top
4830 var multi = typeof options.multi == 'boolean' ? options.multi : false;
4840 var upsert = typeof options.upsert == 'boolean' ? options.upsert : false;
485
486 // Collect errorOptions
4870 var errorOptions = shared._getWriteConcern(self, options);
488
489 // If we have a write command with no callback and w:0 fail
4900 if(errorOptions.w && errorOptions.w != 0 && callback == null) {
4910 throw new Error("writeConcern requires callback")
492 }
493
494 // Create the write command
4950 var write_command = {
496 update: namespace,
497 writeConcern: errorOptions,
498 ordered: !continueOnError,
499 updates: [{
500 q : selector,
501 u: document,
502 multi: multi,
503 upsert: upsert
504 }]
505 }
506
507 // Check if we have a checkKeys override
5080 var checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : false;
509
510 // Execute the write command
5110 self.db.command(write_command
512 , { connection:connection
513 , checkKeys: checkKeys
514 , serializeFunctions: serializeFunctions
515 , writeCommand: true }
516 , function(err, result) {
5170 if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null);
5180 if(errorOptions.w == 0) return;
5190 if(callback == null) return;
5200 if(err != null) {
5210 if(Array.isArray(err.errDetails)) err.code = err.errDetails[0].errCode;
522 // Return the error
5230 return callback(err, null);
524 }
525
526 // Result has an error
5270 if(!result.ok && (result.err != null || result.errmsg != null)) {
528 // Map the error
5290 var error = utils.toError(result);
530 // Backwards compatibility mapping
5310 if(Array.isArray(error.errDetails)) error.code = error.errDetails[0].errCode;
532 // Return the error
5330 return callback(error, null);
534 }
535
536 // Backward compatibility format
5370 var r = backWardsCompatibiltyResults(result, 'update');
538 // Return the results for a whole batch
5390 callback(null, r.n, r)
540 });
541}
542
5431var backWardsCompatibiltyResults = function(result, op) {
544 // Upserted
5450 var upsertedValue = null;
5460 var finalResult = null;
5470 var updatedExisting = true;
548
549 // We have a single document upserted result
5500 if(Array.isArray(result.upserted) || result.upserted != null) {
5510 updatedExisting = false;
5520 upsertedValue = result.upserted;
553 }
554
555 // Final result
5560 if(op == 'remove' || op == 'insert') {
5570 finalResult = {ok: true, n: result.n}
558 } else {
5590 finalResult = {ok: true, n: result.n, updatedExisting: updatedExisting}
560 }
561
5620 if(upsertedValue != null) finalResult.upserted = upsertedValue;
5630 return finalResult;
564}
565
5661var update = function update(selector, document, options, callback) {
5670 if('function' === typeof options) callback = options, options = null;
5680 if(options == null) options = {};
5690 if(!('function' === typeof callback)) callback = null;
570
571 // Get a connection
5720 var connection = this.db.serverConfig.checkoutWriter();
5730 var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true;
574 // If we support write commands let's perform the insert using it
5750 if(!useLegacyOps && hasWriteCommands(connection) && !Buffer.isBuffer(selector) && !Buffer.isBuffer(document)) {
5760 return updateWithWriteCommands(this, selector, document, options, callback);
577 }
578
579 // DbName
5800 var dbName = options['dbName'];
581 // If no dbname defined use the db one
5820 if(dbName == null) {
5830 dbName = this.db.databaseName;
584 }
585
586 // If we are not providing a selector or document throw
5870 if(selector == null || typeof selector != 'object') return callback(new Error("selector must be a valid JavaScript object"));
5880 if(document == null || typeof document != 'object') return callback(new Error("document must be a valid JavaScript object"));
589
590 // Either use override on the function, or go back to default on either the collection
591 // level or db
5920 if(options['serializeFunctions'] != null) {
5930 options['serializeFunctions'] = options['serializeFunctions'];
594 } else {
5950 options['serializeFunctions'] = this.serializeFunctions;
596 }
597
598 // Build the options command
5990 var updateCommand = new UpdateCommand(
600 this.db
601 , dbName + "." + this.collectionName
602 , selector
603 , document
604 , options);
605
6060 var self = this;
607 // Unpack the error options if any
6080 var errorOptions = shared._getWriteConcern(this, options);
609 // If safe is defined check for error message
6100 if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') {
611 // Insert options
6120 var commandOptions = {read:false};
613 // If we have safe set set async to false
6140 if(errorOptions == null) commandOptions['async'] = true;
615 // Set safe option
6160 commandOptions['safe'] = errorOptions;
617 // If we have an error option
6180 if(typeof errorOptions == 'object') {
6190 var keys = Object.keys(errorOptions);
6200 for(var i = 0; i < keys.length; i++) {
6210 commandOptions[keys[i]] = errorOptions[keys[i]];
622 }
623 }
624
625 // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection)
6260 this.db._executeUpdateCommand(updateCommand, commandOptions, function (err, error) {
6270 error = error && error.documents;
6280 if(!callback) return;
629
6300 if(err) {
6310 callback(err);
6320 } else if(error[0].err || error[0].errmsg) {
6330 callback(utils.toError(error[0]));
6340 } else if(error[0].jnote || error[0].wnote || error[0].wtimeout) {
6350 callback(utils.toError(error[0]));
636 } else {
6370 callback(null, error[0].n, error[0]);
638 }
639 });
6400 } else if(shared._hasWriteConcern(errorOptions) && callback == null) {
6410 throw new Error("Cannot use a writeConcern without a provided callback");
642 } else {
643 // Execute update
6440 var result = this.db._executeUpdateCommand(updateCommand);
645 // If no callback just return
6460 if (!callback) return;
647 // If error return error
6480 if (result instanceof Error) {
6490 return callback(result);
650 }
651 // Otherwise just return
6520 return callback();
653 }
654};
655
656// ***************************************************
657// findAndModify function
658// ***************************************************
6591var findAndModify = function findAndModify (query, sort, doc, options, callback) {
6600 var args = Array.prototype.slice.call(arguments, 1);
6610 callback = args.pop();
6620 sort = args.length ? args.shift() || [] : [];
6630 doc = args.length ? args.shift() : null;
6640 options = args.length ? args.shift() || {} : {};
6650 var self = this;
666
6670 var queryObject = {
668 'findandmodify': this.collectionName
669 , 'query': query
670 , 'sort': utils.formattedOrderClause(sort)
671 };
672
6730 queryObject.new = options.new ? 1 : 0;
6740 queryObject.remove = options.remove ? 1 : 0;
6750 queryObject.upsert = options.upsert ? 1 : 0;
676
6770 if (options.fields) {
6780 queryObject.fields = options.fields;
679 }
680
6810 if (doc && !options.remove) {
6820 queryObject.update = doc;
683 }
684
685 // Checkout a write connection
6860 options.connection = self.db.serverConfig.checkoutWriter();
687
688 // Either use override on the function, or go back to default on either the collection
689 // level or db
6900 if(options['serializeFunctions'] != null) {
6910 options['serializeFunctions'] = options['serializeFunctions'];
692 } else {
6930 options['serializeFunctions'] = this.serializeFunctions;
694 }
695
696 // No check on the documents
6970 options.checkKeys = false
698
699 // Execute the command
7000 this.db.command(queryObject
701 , options, function(err, result) {
7020 if(err) return callback(err, null);
7030 return callback(null, result.value, result);
704 });
705}
706
707// ***************************************************
708// findAndRemove function
709// ***************************************************
7101var findAndRemove = function(query, sort, options, callback) {
7110 var args = Array.prototype.slice.call(arguments, 1);
7120 callback = args.pop();
7130 sort = args.length ? args.shift() || [] : [];
7140 options = args.length ? args.shift() || {} : {};
715 // Add the remove option
7160 options['remove'] = true;
717 // Execute the callback
7180 this.findAndModify(query, sort, null, options, callback);
719}
720
721// Map methods
7221exports.insert = insert;
7231exports.remove = remove;
7241exports.save = save;
7251exports.update = update;
7261exports.findAndModify = findAndModify;
7271exports.findAndRemove = findAndRemove;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection/geo.js

13%
38
5
33
LineHitsSource
11var shared = require('./shared')
2 , utils = require('../utils');
3
41var geoNear = function geoNear(x, y, options, callback) {
50 var args = Array.prototype.slice.call(arguments, 2);
60 callback = args.pop();
7 // Fetch all commands
80 options = args.length ? args.shift() || {} : {};
9
10 // Build command object
110 var commandObject = {
12 geoNear:this.collectionName,
13 near: [x, y]
14 }
15
16 // Decorate object if any with known properties
170 if(options['num'] != null) commandObject['num'] = options['num'];
180 if(options['maxDistance'] != null) commandObject['maxDistance'] = options['maxDistance'];
190 if(options['distanceMultiplier'] != null) commandObject['distanceMultiplier'] = options['distanceMultiplier'];
200 if(options['query'] != null) commandObject['query'] = options['query'];
210 if(options['spherical'] != null) commandObject['spherical'] = options['spherical'];
220 if(options['uniqueDocs'] != null) commandObject['uniqueDocs'] = options['uniqueDocs'];
230 if(options['includeLocs'] != null) commandObject['includeLocs'] = options['includeLocs'];
24
25 // Ensure we have the right read preference inheritance
260 options.readPreference = shared._getReadConcern(this, options);
27
28 // Execute the command
290 this.db.command(commandObject, options, function (err, res) {
300 if (err) {
310 callback(err);
320 } else if (res.err || res.errmsg) {
330 callback(utils.toError(res));
34 } else {
35 // should we only be returning res.results here? Not sure if the user
36 // should see the other return information
370 callback(null, res);
38 }
39 });
40}
41
421var geoHaystackSearch = function geoHaystackSearch(x, y, options, callback) {
430 var args = Array.prototype.slice.call(arguments, 2);
440 callback = args.pop();
45 // Fetch all commands
460 options = args.length ? args.shift() || {} : {};
47
48 // Build command object
490 var commandObject = {
50 geoSearch:this.collectionName,
51 near: [x, y]
52 }
53
54 // Decorate object if any with known properties
550 if(options['maxDistance'] != null) commandObject['maxDistance'] = options['maxDistance'];
560 if(options['query'] != null) commandObject['search'] = options['query'];
570 if(options['search'] != null) commandObject['search'] = options['search'];
580 if(options['limit'] != null) commandObject['limit'] = options['limit'];
59
60 // Ensure we have the right read preference inheritance
610 options.readPreference = shared._getReadConcern(this, options);
62
63 // Execute the command
640 this.db.command(commandObject, options, function (err, res) {
650 if (err) {
660 callback(err);
670 } else if (res.err || res.errmsg) {
680 callback(utils.toError(res));
69 } else {
70 // should we only be returning res.results here? Not sure if the user
71 // should see the other return information
720 callback(null, res);
73 }
74 });
75}
76
771exports.geoNear = geoNear;
781exports.geoHaystackSearch = geoHaystackSearch;
79

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection/index.js

28%
39
11
28
LineHitsSource
11var _getWriteConcern = require('./shared')._getWriteConcern;
2
31var createIndex = function createIndex (fieldOrSpec, options, callback) {
4 // Clean up call
50 var args = Array.prototype.slice.call(arguments, 1);
60 callback = args.pop();
70 options = args.length ? args.shift() || {} : {};
80 options = typeof callback === 'function' ? options : callback;
90 options = options == null ? {} : options;
10
11 // Collect errorOptions
120 var errorOptions = _getWriteConcern(this, options);
13 // Execute create index
140 this.db.createIndex(this.collectionName, fieldOrSpec, options, callback);
15};
16
171var indexExists = function indexExists(indexes, callback) {
180 this.indexInformation(function(err, indexInformation) {
19 // If we have an error return
200 if(err != null) return callback(err, null);
21 // Let's check for the index names
220 if(Array.isArray(indexes)) {
230 for(var i = 0; i < indexes.length; i++) {
240 if(indexInformation[indexes[i]] == null) {
250 return callback(null, false);
26 }
27 }
28
29 // All keys found return true
300 return callback(null, true);
31 } else {
320 return callback(null, indexInformation[indexes] != null);
33 }
34 });
35}
36
371var dropAllIndexes = function dropIndexes (callback) {
380 this.db.dropIndex(this.collectionName, '*', function (err, result) {
390 if(err) return callback(err, false);
400 callback(null, true);
41 });
42};
43
441var indexInformation = function indexInformation (options, callback) {
45 // Unpack calls
460 var args = Array.prototype.slice.call(arguments, 0);
470 callback = args.pop();
480 options = args.length ? args.shift() || {} : {};
49 // Call the index information
500 this.db.indexInformation(this.collectionName, options, callback);
51};
52
531var ensureIndex = function ensureIndex (fieldOrSpec, options, callback) {
54 // Clean up call
550 if (typeof callback === 'undefined' && typeof options === 'function') {
560 callback = options;
570 options = {};
58 }
59
600 if (options == null) {
610 options = {};
62 }
63
64 // Execute create index
650 this.db.ensureIndex(this.collectionName, fieldOrSpec, options, callback);
66};
67
681exports.createIndex = createIndex;
691exports.indexExists = indexExists;
701exports.dropAllIndexes = dropAllIndexes;
711exports.indexInformation = indexInformation;
721exports.ensureIndex = ensureIndex;
73

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection/query.js

8%
75
6
69
LineHitsSource
11var ObjectID = require('bson').ObjectID
2 , Scope = require('../scope').Scope
3 , shared = require('./shared')
4 , utils = require('../utils');
5
61var testForFields = {
7 limit: 1, sort: 1, fields:1, skip: 1, hint: 1, explain: 1, snapshot: 1, timeout: 1, tailable: 1, tailableRetryInterval: 1
8 , numberOfRetries: 1, awaitdata: 1, exhaust: 1, batchSize: 1, returnKey: 1, maxScan: 1, min: 1, max: 1, showDiskLoc: 1
9 , comment: 1, raw: 1, readPreference: 1, partial: 1, read: 1, dbName: 1, oplogReplay: 1
10};
11
12//
13// Find method
14//
151var find = function find () {
160 var options
17 , args = Array.prototype.slice.call(arguments, 0)
18 , has_callback = typeof args[args.length - 1] === 'function'
19 , has_weird_callback = typeof args[0] === 'function'
20 , callback = has_callback ? args.pop() : (has_weird_callback ? args.shift() : null)
21 , len = args.length
22 , selector = len >= 1 ? args[0] : {}
23 , fields = len >= 2 ? args[1] : undefined;
24
250 if(len === 1 && has_weird_callback) {
26 // backwards compat for callback?, options case
270 selector = {};
280 options = args[0];
29 }
30
310 if(len === 2 && !Array.isArray(fields)) {
320 var fieldKeys = Object.getOwnPropertyNames(fields);
330 var is_option = false;
34
350 for(var i = 0; i < fieldKeys.length; i++) {
360 if(testForFields[fieldKeys[i]] != null) {
370 is_option = true;
380 break;
39 }
40 }
41
420 if(is_option) {
430 options = fields;
440 fields = undefined;
45 } else {
460 options = {};
47 }
480 } else if(len === 2 && Array.isArray(fields) && !Array.isArray(fields[0])) {
490 var newFields = {};
50 // Rewrite the array
510 for(var i = 0; i < fields.length; i++) {
520 newFields[fields[i]] = 1;
53 }
54 // Set the fields
550 fields = newFields;
56 }
57
580 if(3 === len) {
590 options = args[2];
60 }
61
62 // Ensure selector is not null
630 selector = selector == null ? {} : selector;
64 // Validate correctness off the selector
650 var object = selector;
660 if(Buffer.isBuffer(object)) {
670 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
680 if(object_size != object.length) {
690 var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
700 error.name = 'MongoError';
710 throw error;
72 }
73 }
74
75 // Validate correctness of the field selector
760 var object = fields;
770 if(Buffer.isBuffer(object)) {
780 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
790 if(object_size != object.length) {
800 var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
810 error.name = 'MongoError';
820 throw error;
83 }
84 }
85
86 // Check special case where we are using an objectId
870 if(selector instanceof ObjectID || (selector != null && selector._bsontype == 'ObjectID')) {
880 selector = {_id:selector};
89 }
90
91 // If it's a serialized fields field we need to just let it through
92 // user be warned it better be good
930 if(options && options.fields && !(Buffer.isBuffer(options.fields))) {
940 fields = {};
95
960 if(Array.isArray(options.fields)) {
970 if(!options.fields.length) {
980 fields['_id'] = 1;
99 } else {
1000 for (var i = 0, l = options.fields.length; i < l; i++) {
1010 fields[options.fields[i]] = 1;
102 }
103 }
104 } else {
1050 fields = options.fields;
106 }
107 }
108
1090 if (!options) options = {};
1100 options.skip = len > 3 ? args[2] : options.skip ? options.skip : 0;
1110 options.limit = len > 3 ? args[3] : options.limit ? options.limit : 0;
1120 options.raw = options.raw != null && typeof options.raw === 'boolean' ? options.raw : this.raw;
1130 options.hint = options.hint != null ? shared.normalizeHintField(options.hint) : this.internalHint;
1140 options.timeout = len == 5 ? args[4] : typeof options.timeout === 'undefined' ? undefined : options.timeout;
115 // If we have overridden slaveOk otherwise use the default db setting
1160 options.slaveOk = options.slaveOk != null ? options.slaveOk : this.db.slaveOk;
117
118 // Set option
1190 var o = options;
120 // Support read/readPreference
1210 if(o["read"] != null) o["readPreference"] = o["read"];
122 // Set the read preference
1230 o.read = o["readPreference"] ? o.readPreference : this.readPreference;
124 // Adjust slave ok if read preference is secondary or secondary only
1250 if(o.read == "secondary" || o.read == "secondaryOnly") options.slaveOk = true;
126
127 // Set the selector
1280 o.selector = selector;
129
130 // Create precursor
1310 var scope = new Scope(this, {}, fields, o);
132 // Callback for backward compatibility
1330 if(callback) return callback(null, scope.find(selector));
134 // Return the pre cursor object
1350 return scope.find(selector);
136};
137
1381var findOne = function findOne () {
1390 var self = this;
1400 var args = Array.prototype.slice.call(arguments, 0);
1410 var callback = args.pop();
1420 var cursor = this.find.apply(this, args).limit(-1).batchSize(1);
143
144 // Return the item
1450 cursor.nextObject(function(err, item) {
1460 if(err != null) return callback(utils.toError(err), null);
1470 callback(null, item);
148 });
149};
150
151
1521exports.find = find;
1531exports.findOne = findOne;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection/shared.js

16%
65
11
54
LineHitsSource
1// ***************************************************
2// Write concerns
3// ***************************************************
41var _hasWriteConcern = function(errorOptions) {
50 return errorOptions == true
6 || errorOptions.w > 0
7 || errorOptions.w == 'majority'
8 || errorOptions.j == true
9 || errorOptions.journal == true
10 || errorOptions.fsync == true
11}
12
131var _setWriteConcernHash = function(options) {
140 var finalOptions = {};
150 if(options.w != null) finalOptions.w = options.w;
160 if(options.journal == true) finalOptions.j = options.journal;
170 if(options.j == true) finalOptions.j = options.j;
180 if(options.fsync == true) finalOptions.fsync = options.fsync;
190 if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout;
200 return finalOptions;
21}
22
231var _getWriteConcern = function(self, options) {
24 // Final options
250 var finalOptions = {w:1};
26 // Local options verification
270 if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') {
280 finalOptions = _setWriteConcernHash(options);
290 } else if(typeof options.safe == "boolean") {
300 finalOptions = {w: (options.safe ? 1 : 0)};
310 } else if(options.safe != null && typeof options.safe == 'object') {
320 finalOptions = _setWriteConcernHash(options.safe);
330 } else if(self.opts.w != null || typeof self.opts.j == 'boolean' || typeof self.opts.journal == 'boolean' || typeof self.opts.fsync == 'boolean') {
340 finalOptions = _setWriteConcernHash(self.opts);
350 } else if(typeof self.opts.safe == "boolean") {
360 finalOptions = {w: (self.opts.safe ? 1 : 0)};
370 } else if(self.db.safe.w != null || typeof self.db.safe.j == 'boolean' || typeof self.db.safe.journal == 'boolean' || typeof self.db.safe.fsync == 'boolean') {
380 finalOptions = _setWriteConcernHash(self.db.safe);
390 } else if(self.db.options.w != null || typeof self.db.options.j == 'boolean' || typeof self.db.options.journal == 'boolean' || typeof self.db.options.fsync == 'boolean') {
400 finalOptions = _setWriteConcernHash(self.db.options);
410 } else if(typeof self.db.safe == "boolean") {
420 finalOptions = {w: (self.db.safe ? 1 : 0)};
43 }
44
45 // Ensure we don't have an invalid combination of write concerns
460 if(finalOptions.w < 1
470 && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowlegement using w < 1 cannot be combined with journal:true or fsync:true");
48
49 // Return the options
500 return finalOptions;
51}
52
531var _getReadConcern = function(self, options) {
540 if(options.readPreference) return options.readPreference;
550 if(self.readPreference) return self.readPreference;
560 if(self.db.readPreference) return self.readPreference;
570 return 'primary';
58}
59
60/**
61 * @ignore
62 */
631var checkCollectionName = function checkCollectionName (collectionName) {
640 if('string' !== typeof collectionName) {
650 throw Error("collection name must be a String");
66 }
67
680 if(!collectionName || collectionName.indexOf('..') != -1) {
690 throw Error("collection names cannot be empty");
70 }
71
720 if(collectionName.indexOf('$') != -1 &&
73 collectionName.match(/((^\$cmd)|(oplog\.\$main))/) == null) {
740 throw Error("collection names must not contain '$'");
75 }
76
770 if(collectionName.match(/^\.|\.$/) != null) {
780 throw Error("collection names must not start or end with '.'");
79 }
80
81 // Validate that we are not passing 0x00 in the colletion name
820 if(!!~collectionName.indexOf("\x00")) {
830 throw new Error("collection names cannot contain a null character");
84 }
85};
86
87
88/**
89 * Normalizes a `hint` argument.
90 *
91 * @param {String|Object|Array} hint
92 * @return {Object}
93 * @api private
94 */
951var normalizeHintField = function normalizeHintField(hint) {
960 var finalHint = null;
97
980 if(typeof hint == 'string') {
990 finalHint = hint;
1000 } else if(Array.isArray(hint)) {
1010 finalHint = {};
102
1030 hint.forEach(function(param) {
1040 finalHint[param] = 1;
105 });
1060 } else if(hint != null && typeof hint == 'object') {
1070 finalHint = {};
1080 for (var name in hint) {
1090 finalHint[name] = hint[name];
110 }
111 }
112
1130 return finalHint;
114};
115
1161exports._getWriteConcern = _getWriteConcern;
1171exports._hasWriteConcern = _hasWriteConcern;
1181exports._getReadConcern = _getReadConcern;
1191exports.checkCollectionName = checkCollectionName;
1201exports.normalizeHintField = normalizeHintField;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/command_cursor.js

2%
142
3
139
LineHitsSource
11var Long = require('bson').Long
2 , GetMoreCommand = require('./commands/get_more_command').GetMoreCommand;
3
41var CommandCursor = function(db, collection, command, options) {
5 // Ensure empty options if no options passed
60 options = options || {};
7
8 // Default cursor id is 0
90 var cursorId = Long.fromInt(0);
100 var zeroCursor = Long.fromInt(0);
110 var state = 'init';
12
13 // Hardcode batch size
140 command.cursor.batchSize = 1;
15
16 // BatchSize
170 var batchSize = command.cursor.batchSize || 0;
180 var raw = options.raw || false;
190 var readPreference = options.readPreference || 'primary';
20
21 // Checkout a connection
220 var connection = db.serverConfig.checkoutReader(readPreference);
23 // MaxTimeMS
240 var maxTimeMS = options.maxTimeMS;
25
26 // Contains all the items
270 var items = null;
28
29 // Execute getmore
300 var getMore = function(callback) {
31 // Resolve more of the cursor using the getMore command
320 var getMoreCommand = new GetMoreCommand(db
33 , db.databaseName + "." + collection.collectionName
34 , batchSize
35 , cursorId
36 );
37
38 // Set up options
390 var command_options = { connection:connection };
40
41 // Execute the getMore Command
420 db._executeQueryCommand(getMoreCommand, command_options, function(err, result) {
430 if(err) {
440 items = [];
450 state = 'closed';
460 return callback(err);
47 }
48
49 // Return all the documents
500 callback(null, result);
51 });
52 }
53
540 var exhaustGetMore = function(callback) {
550 getMore(function(err, result) {
560 if(err) {
570 items = [];
580 state = 'closed';
590 return callback(err, null);
60 }
61
62 // Add the items
630 items = items.concat(result.documents);
64
65 // Set the cursor id
660 cursorId = result.cursorId;
670 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
68
69 // If the cursor is done
700 if(result.cursorId.equals(zeroCursor)) {
710 return callback(null, items);
72 }
73
74 // Check the cursor id
750 exhaustGetMore(callback);
76 });
77 }
78
790 var exhaustGetMoreEach = function(callback) {
800 getMore(function(err, result) {
810 if(err) {
820 items = [];
830 state = 'closed';
840 return callback(err, null);
85 }
86
87 // Add the items
880 items = result.documents;
89
90 // Emit all the items in the first batch
910 while(items.length > 0) {
920 callback(null, items.shift());
93 }
94
95 // Set the cursor id
960 cursorId = result.cursorId;
970 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
98
99 // If the cursor is done
1000 if(result.cursorId.equals(zeroCursor)) {
1010 state = "closed";
1020 return callback(null, null);
103 }
104
105 // Check the cursor id
1060 exhaustGetMoreEach(callback);
107 });
108 }
109
110 //
111 // Get all the elements
112 //
1130 this.get = function(options, callback) {
1140 if(typeof options == 'function') {
1150 callback = options;
1160 options = {};
117 }
118
119 // Set the connection to the passed in one if it's provided
1200 connection = options.connection ? options.connection : connection;
121
122 // Command options
1230 var _options = {connection:connection};
1240 if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS;
125
126 // Execute the internal command first
1270 db.command(command, _options, function(err, result) {
1280 if(err) {
1290 state = 'closed';
1300 return callback(err, null);
131 }
132
133 // Retrieve the cursor id
1340 cursorId = result.cursor.id;
1350 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
136
137 // Validate cursorId
1380 if(cursorId.equals(zeroCursor)) {
1390 return callback(null, result.cursor.firstBatch);
140 };
141
142 // Add to the items
1430 items = result.cursor.firstBatch;
144 // Execute the getMore
1450 exhaustGetMore(callback);
146 });
147 }
148
149 //
150 // Iterate over all the items
151 //
1520 this.each = function(options, callback) {
1530 if(typeof options == 'function') {
1540 callback = options;
1550 options = {};
156 }
157
158 // If it's a closed cursor return error
1590 if(this.isClosed()) return callback(new Error("cursor is closed"));
160 // Set the connection to the passed in one if it's provided
1610 connection = options.connection ? options.connection : connection;
162
163 // Command options
1640 var _options = {connection:connection};
1650 if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS;
166
167 // Execute the internal command first
1680 db.command(command, _options, function(err, result) {
1690 if(err) {
1700 state = 'closed';
1710 return callback(err, null);
172 }
173
174 // Get all the items
1750 items = result.cursor.firstBatch;
176
177 // Emit all the items in the first batch
1780 while(items.length > 0) {
1790 callback(null, items.shift());
180 }
181
182 // Retrieve the cursor id
1830 cursorId = result.cursor.id;
1840 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
185
186 // If no cursor we just finish up the current batch of items
1870 if(cursorId.equals(zeroCursor)) {
1880 state = 'closed';
1890 return callback(null, null);
190 }
191
192 // Emit each until no more getMore's
1930 exhaustGetMoreEach(callback);
194 });
195 }
196
197 //
198 // Get the next object
199 //
2000 this.next = function(options, callback) {
2010 if(typeof options == 'function') {
2020 callback = options;
2030 options = {};
204 }
205
206 // If it's a closed cursor return error
2070 if(this.isClosed()) return callback(new Error("cursor is closed"));
208
209 // Set the connection to the passed in one if it's provided
2100 connection = options.connection ? options.connection : connection;
211
212 // Command options
2130 var _options = {connection:connection};
2140 if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS;
215
216 // Execute the internal command first
2170 if(!items) {
2180 db.command(command, _options, function(err, result) {
2190 if(err) {
2200 state = 'closed';
2210 return callback(err, null);
222 }
223
224 // Retrieve the cursor id
2250 cursorId = result.cursor.id;
2260 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
227 // Get the first batch results
2280 items = result.cursor.firstBatch;
229 // We have items return the first one
2300 if(items.length > 0) {
2310 callback(null, items.shift());
232 } else {
2330 state = 'closed';
2340 callback(null, null);
235 }
236 });
2370 } else if(items.length > 0) {
2380 callback(null, items.shift());
2390 } else if(items.length == 0 && cursorId.equals(zeroCursor)) {
2400 state = 'closed';
2410 callback(null, null);
242 } else {
243 // Execute a getMore
2440 getMore(function(err, result) {
2450 if(err) {
2460 state = 'closed';
2470 return callback(err, null);
248 }
249
250 // Set the cursor id
2510 cursorId = result.cursorId;
2520 if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId);
253
254 // Add the items
2550 items = items.concat(result.documents);
256 // If no more items
2570 if(items.length == 0) {
2580 state = 'closed';
2590 return callback(null, null);
260 }
261
262 // Return the item
2630 return callback(null, items.shift());
264 })
265 }
266 }
267
268 // Validate if the cursor is closed
2690 this.isClosed = function() {
2700 return state == 'closed';
271 }
272
273 // Allow us to set the MaxTimeMS
2740 this.maxTimeMS = function(_maxTimeMS) {
2750 maxTimeMS = _maxTimeMS;
276 }
277
278 // Close the cursor sending a kill cursor command if needed
2790 this.close = function(options, callback) {
2800 if(typeof options == 'function') {
2810 callback = options;
2820 options = {};
283 }
284
285 // Close the cursor if not needed
2860 if(cursorId instanceof Long && cursorId.greaterThan(Long.fromInt(0))) {
2870 try {
2880 var command = new KillCursorCommand(this.db, [cursorId]);
289 // Added an empty callback to ensure we don't throw any null exceptions
2900 db._executeQueryCommand(command, {connection:connection});
291 } catch(err) {}
292 }
293
294 // Null out the connection
2950 connection = null;
296 // Reset cursor id
2970 cursorId = Long.fromInt(0);
298 // Set to closed status
2990 state = 'closed';
300 // Clear out all the items
3010 items = null;
302
3030 if(callback) {
3040 callback(null, null);
305 }
306 }
307}
308
3091exports.CommandCursor = CommandCursor;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/base_command.js

77%
18
14
4
LineHitsSource
1/**
2 Base object used for common functionality
3**/
41var BaseCommand = exports.BaseCommand = function BaseCommand() {
5};
6
71var id = 1;
81BaseCommand.prototype.getRequestId = function getRequestId() {
90 if (!this.requestId) this.requestId = id++;
100 return this.requestId;
11};
12
131BaseCommand.prototype.setMongosReadPreference = function setMongosReadPreference(readPreference, tags) {}
14
151BaseCommand.prototype.updateRequestId = function() {
160 this.requestId = id++;
170 return this.requestId;
18};
19
20// OpCodes
211BaseCommand.OP_REPLY = 1;
221BaseCommand.OP_MSG = 1000;
231BaseCommand.OP_UPDATE = 2001;
241BaseCommand.OP_INSERT = 2002;
251BaseCommand.OP_GET_BY_OID = 2003;
261BaseCommand.OP_QUERY = 2004;
271BaseCommand.OP_GET_MORE = 2005;
281BaseCommand.OP_DELETE = 2006;
291BaseCommand.OP_KILL_CURSORS = 2007;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/db_command.js

24%
128
31
97
LineHitsSource
11var QueryCommand = require('./query_command').QueryCommand,
2 InsertCommand = require('./insert_command').InsertCommand,
3 inherits = require('util').inherits,
4 utils = require('../utils'),
5 crypto = require('crypto');
6
7/**
8 Db Command
9**/
101var DbCommand = exports.DbCommand = function(dbInstance, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) {
110 QueryCommand.call(this);
120 this.collectionName = collectionName;
130 this.queryOptions = queryOptions;
140 this.numberToSkip = numberToSkip;
150 this.numberToReturn = numberToReturn;
160 this.query = query;
170 this.returnFieldSelector = returnFieldSelector;
180 this.db = dbInstance;
19
20 // Set the slave ok bit
210 if(this.db && this.db.slaveOk) {
220 this.queryOptions |= QueryCommand.OPTS_SLAVE;
23 }
24
25 // Make sure we don't get a null exception
260 options = options == null ? {} : options;
27
28 // Allow for overriding the BSON checkKeys function
290 this.checkKeys = typeof options['checkKeys'] == 'boolean' ? options["checkKeys"] : true;
30
31 // Let us defined on a command basis if we want functions to be serialized or not
320 if(options['serializeFunctions'] != null && options['serializeFunctions']) {
330 this.serializeFunctions = true;
34 }
35};
36
371inherits(DbCommand, QueryCommand);
38
39// Constants
401DbCommand.SYSTEM_NAMESPACE_COLLECTION = "system.namespaces";
411DbCommand.SYSTEM_INDEX_COLLECTION = "system.indexes";
421DbCommand.SYSTEM_PROFILE_COLLECTION = "system.profile";
431DbCommand.SYSTEM_USER_COLLECTION = "system.users";
441DbCommand.SYSTEM_COMMAND_COLLECTION = "$cmd";
451DbCommand.SYSTEM_JS_COLLECTION = "system.js";
46
47// New commands
481DbCommand.NcreateIsMasterCommand = function(db, databaseName) {
490 return new DbCommand(db, databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null);
50};
51
52// Provide constructors for different db commands
531DbCommand.createIsMasterCommand = function(db) {
540 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null);
55};
56
571DbCommand.createCollectionInfoCommand = function(db, selector) {
580 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_NAMESPACE_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, 0, selector, null);
59};
60
611DbCommand.createGetNonceCommand = function(db, options) {
620 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'getnonce':1}, null);
63};
64
651DbCommand.createAuthenticationCommand = function(db, username, password, nonce, authdb) {
66 // Use node md5 generator
670 var md5 = crypto.createHash('md5');
68 // Generate keys used for authentication
690 md5.update(username + ":mongo:" + password);
700 var hash_password = md5.digest('hex');
71 // Final key
720 md5 = crypto.createHash('md5');
730 md5.update(nonce + username + hash_password);
740 var key = md5.digest('hex');
75 // Creat selector
760 var selector = {'authenticate':1, 'user':username, 'nonce':nonce, 'key':key};
77 // Create db command
780 return new DbCommand(db, authdb + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NONE, 0, -1, selector, null);
79};
80
811DbCommand.createLogoutCommand = function(db) {
820 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'logout':1}, null);
83};
84
851DbCommand.createCreateCollectionCommand = function(db, collectionName, options) {
860 var selector = {'create':collectionName};
87 // Modify the options to ensure correct behaviour
880 for(var name in options) {
890 if(options[name] != null && options[name].constructor != Function) selector[name] = options[name];
90 }
91 // Execute the command
920 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, selector, null);
93};
94
951DbCommand.createDropCollectionCommand = function(db, collectionName) {
960 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'drop':collectionName}, null);
97};
98
991DbCommand.createRenameCollectionCommand = function(db, fromCollectionName, toCollectionName, options) {
1000 var renameCollection = db.databaseName + "." + fromCollectionName;
1010 var toCollection = db.databaseName + "." + toCollectionName;
1020 var dropTarget = options && options.dropTarget ? options.dropTarget : false;
1030 return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'renameCollection':renameCollection, 'to':toCollection, 'dropTarget':dropTarget}, null);
104};
105
1061DbCommand.createGetLastErrorCommand = function(options, db) {
107
1080 if (typeof db === 'undefined') {
1090 db = options;
1100 options = {};
111 }
112 // Final command
1130 var command = {'getlasterror':1};
114 // If we have an options Object let's merge in the fields (fsync/wtimeout/w)
1150 if('object' === typeof options) {
1160 for(var name in options) {
1170 command[name] = options[name]
118 }
119 }
120
121 // Special case for w == 1, remove the w
1220 if(1 == command.w) {
1230 delete command.w;
124 }
125
126 // Execute command
1270 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command, null);
128};
129
1301DbCommand.createGetLastStatusCommand = DbCommand.createGetLastErrorCommand;
131
1321DbCommand.createGetPreviousErrorsCommand = function(db) {
1330 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'getpreverror':1}, null);
134};
135
1361DbCommand.createResetErrorHistoryCommand = function(db) {
1370 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'reseterror':1}, null);
138};
139
1401DbCommand.createCreateIndexCommand = function(db, collectionName, fieldOrSpec, options) {
1410 var fieldHash = {};
1420 var indexes = [];
1430 var keys;
144
145 // Get all the fields accordingly
1460 if('string' == typeof fieldOrSpec) {
147 // 'type'
1480 indexes.push(fieldOrSpec + '_' + 1);
1490 fieldHash[fieldOrSpec] = 1;
150
1510 } else if(utils.isArray(fieldOrSpec)) {
152
1530 fieldOrSpec.forEach(function(f) {
1540 if('string' == typeof f) {
155 // [{location:'2d'}, 'type']
1560 indexes.push(f + '_' + 1);
1570 fieldHash[f] = 1;
1580 } else if(utils.isArray(f)) {
159 // [['location', '2d'],['type', 1]]
1600 indexes.push(f[0] + '_' + (f[1] || 1));
1610 fieldHash[f[0]] = f[1] || 1;
1620 } else if(utils.isObject(f)) {
163 // [{location:'2d'}, {type:1}]
1640 keys = Object.keys(f);
1650 keys.forEach(function(k) {
1660 indexes.push(k + '_' + f[k]);
1670 fieldHash[k] = f[k];
168 });
169 } else {
170 // undefined (ignore)
171 }
172 });
173
1740 } else if(utils.isObject(fieldOrSpec)) {
175 // {location:'2d', type:1}
1760 keys = Object.keys(fieldOrSpec);
1770 keys.forEach(function(key) {
1780 indexes.push(key + '_' + fieldOrSpec[key]);
1790 fieldHash[key] = fieldOrSpec[key];
180 });
181 }
182
183 // Generate the index name
1840 var indexName = typeof options.name == 'string'
185 ? options.name
186 : indexes.join("_");
187
1880 var selector = {
189 'ns': db.databaseName + "." + collectionName,
190 'key': fieldHash,
191 'name': indexName
192 }
193
194 // Ensure we have a correct finalUnique
1950 var finalUnique = options == null || 'object' === typeof options
196 ? false
197 : options;
198
199 // Set up options
2000 options = options == null || typeof options == 'boolean'
201 ? {}
202 : options;
203
204 // Add all the options
2050 var keys = Object.keys(options);
2060 for(var i = 0; i < keys.length; i++) {
2070 selector[keys[i]] = options[keys[i]];
208 }
209
2100 if(selector['unique'] == null)
2110 selector['unique'] = finalUnique;
212
2130 var name = db.databaseName + "." + DbCommand.SYSTEM_INDEX_COLLECTION;
2140 var cmd = new InsertCommand(db, name, false);
2150 return cmd.add(selector);
216};
217
2181DbCommand.logoutCommand = function(db, command_hash, options) {
2190 var dbName = options != null && options['authdb'] != null ? options['authdb'] : db.databaseName;
2200 return new DbCommand(db, dbName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null);
221}
222
2231DbCommand.createDropIndexCommand = function(db, collectionName, indexName) {
2240 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'deleteIndexes':collectionName, 'index':indexName}, null);
225};
226
2271DbCommand.createReIndexCommand = function(db, collectionName) {
2280 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'reIndex':collectionName}, null);
229};
230
2311DbCommand.createDropDatabaseCommand = function(db) {
2320 return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'dropDatabase':1}, null);
233};
234
2351DbCommand.createDbCommand = function(db, command_hash, options, auth_db) {
2360 var db_name = (auth_db ? auth_db : db.databaseName) + "." + DbCommand.SYSTEM_COMMAND_COLLECTION;
2370 options = options == null ? {checkKeys: false} : options;
2380 return new DbCommand(db, db_name, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null, options);
239};
240
2411DbCommand.createAdminDbCommand = function(db, command_hash) {
2420 return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null);
243};
244
2451DbCommand.createAdminDbCommandSlaveOk = function(db, command_hash) {
2460 return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null);
247};
248
2491DbCommand.createDbSlaveOkCommand = function(db, command_hash, options) {
2500 options = options == null ? {checkKeys: false} : options;
2510 var dbName = options.dbName ? options.dbName : db.databaseName;
2520 return new DbCommand(db, dbName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null, options);
253};
254

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/delete_command.js

7%
68
5
63
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits;
3
4/**
5 Insert Document Command
6**/
71var DeleteCommand = exports.DeleteCommand = function(db, collectionName, selector, flags) {
80 BaseCommand.call(this);
9
10 // Validate correctness off the selector
110 var object = selector;
120 if(Buffer.isBuffer(object)) {
130 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
140 if(object_size != object.length) {
150 var error = new Error("delete raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
160 error.name = 'MongoError';
170 throw error;
18 }
19 }
20
210 this.flags = flags;
220 this.collectionName = collectionName;
230 this.selector = selector;
240 this.db = db;
25};
26
271inherits(DeleteCommand, BaseCommand);
28
291DeleteCommand.OP_DELETE = 2006;
30
31/*
32struct {
33 MsgHeader header; // standard message header
34 int32 ZERO; // 0 - reserved for future use
35 cstring fullCollectionName; // "dbname.collectionname"
36 int32 ZERO; // 0 - reserved for future use
37 mongo.BSON selector; // query object. See below for details.
38}
39*/
401DeleteCommand.prototype.toBinary = function(bsonSettings) {
41 // Validate that we are not passing 0x00 in the colletion name
420 if(!!~this.collectionName.indexOf("\x00")) {
430 throw new Error("namespace cannot contain a null character");
44 }
45
46 // Calculate total length of the document
470 var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.selector, false, true) + (4 * 4);
48
49 // Enforce maximum bson size
500 if(!bsonSettings.disableDriverBSONSizeCheck
51 && totalLengthOfCommand > bsonSettings.maxBsonSize)
520 throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
53
540 if(bsonSettings.disableDriverBSONSizeCheck
55 && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
560 throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
57
58 // Let's build the single pass buffer command
590 var _index = 0;
600 var _command = new Buffer(totalLengthOfCommand);
61 // Write the header information to the buffer
620 _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
630 _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
640 _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
650 _command[_index] = totalLengthOfCommand & 0xff;
66 // Adjust index
670 _index = _index + 4;
68 // Write the request ID
690 _command[_index + 3] = (this.requestId >> 24) & 0xff;
700 _command[_index + 2] = (this.requestId >> 16) & 0xff;
710 _command[_index + 1] = (this.requestId >> 8) & 0xff;
720 _command[_index] = this.requestId & 0xff;
73 // Adjust index
740 _index = _index + 4;
75 // Write zero
760 _command[_index++] = 0;
770 _command[_index++] = 0;
780 _command[_index++] = 0;
790 _command[_index++] = 0;
80 // Write the op_code for the command
810 _command[_index + 3] = (DeleteCommand.OP_DELETE >> 24) & 0xff;
820 _command[_index + 2] = (DeleteCommand.OP_DELETE >> 16) & 0xff;
830 _command[_index + 1] = (DeleteCommand.OP_DELETE >> 8) & 0xff;
840 _command[_index] = DeleteCommand.OP_DELETE & 0xff;
85 // Adjust index
860 _index = _index + 4;
87
88 // Write zero
890 _command[_index++] = 0;
900 _command[_index++] = 0;
910 _command[_index++] = 0;
920 _command[_index++] = 0;
93
94 // Write the collection name to the command
950 _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
960 _command[_index - 1] = 0;
97
98 // Write the flags
990 _command[_index + 3] = (this.flags >> 24) & 0xff;
1000 _command[_index + 2] = (this.flags >> 16) & 0xff;
1010 _command[_index + 1] = (this.flags >> 8) & 0xff;
1020 _command[_index] = this.flags & 0xff;
103 // Adjust index
1040 _index = _index + 4;
105
106 // Document binary length
1070 var documentLength = 0
108
109 // Serialize the selector
110 // If we are passing a raw buffer, do minimal validation
1110 if(Buffer.isBuffer(this.selector)) {
1120 documentLength = this.selector.length;
113 // Copy the data into the current buffer
1140 this.selector.copy(_command, _index);
115 } else {
1160 documentLength = this.db.bson.serializeWithBufferAndIndex(this.selector, false, _command, _index) - _index + 1;
117 }
118
119 // Write the length to the document
1200 _command[_index + 3] = (documentLength >> 24) & 0xff;
1210 _command[_index + 2] = (documentLength >> 16) & 0xff;
1220 _command[_index + 1] = (documentLength >> 8) & 0xff;
1230 _command[_index] = documentLength & 0xff;
124 // Update index in buffer
1250 _index = _index + documentLength;
126 // Add terminating 0 for the object
1270 _command[_index - 1] = 0;
1280 return _command;
129};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/get_more_command.js

9%
52
5
47
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits,
3 binaryutils = require('../utils');
4
5/**
6 Get More Document Command
7**/
81var GetMoreCommand = exports.GetMoreCommand = function(db, collectionName, numberToReturn, cursorId) {
90 BaseCommand.call(this);
10
110 this.collectionName = collectionName;
120 this.numberToReturn = numberToReturn;
130 this.cursorId = cursorId;
140 this.db = db;
15};
16
171inherits(GetMoreCommand, BaseCommand);
18
191GetMoreCommand.OP_GET_MORE = 2005;
20
211GetMoreCommand.prototype.toBinary = function() {
22 // Validate that we are not passing 0x00 in the colletion name
230 if(!!~this.collectionName.indexOf("\x00")) {
240 throw new Error("namespace cannot contain a null character");
25 }
26
27 // Calculate total length of the document
280 var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 8 + (4 * 4);
29 // Let's build the single pass buffer command
300 var _index = 0;
310 var _command = new Buffer(totalLengthOfCommand);
32 // Write the header information to the buffer
330 _command[_index++] = totalLengthOfCommand & 0xff;
340 _command[_index++] = (totalLengthOfCommand >> 8) & 0xff;
350 _command[_index++] = (totalLengthOfCommand >> 16) & 0xff;
360 _command[_index++] = (totalLengthOfCommand >> 24) & 0xff;
37
38 // Write the request ID
390 _command[_index++] = this.requestId & 0xff;
400 _command[_index++] = (this.requestId >> 8) & 0xff;
410 _command[_index++] = (this.requestId >> 16) & 0xff;
420 _command[_index++] = (this.requestId >> 24) & 0xff;
43
44 // Write zero
450 _command[_index++] = 0;
460 _command[_index++] = 0;
470 _command[_index++] = 0;
480 _command[_index++] = 0;
49
50 // Write the op_code for the command
510 _command[_index++] = GetMoreCommand.OP_GET_MORE & 0xff;
520 _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 8) & 0xff;
530 _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 16) & 0xff;
540 _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 24) & 0xff;
55
56 // Write zero
570 _command[_index++] = 0;
580 _command[_index++] = 0;
590 _command[_index++] = 0;
600 _command[_index++] = 0;
61
62 // Write the collection name to the command
630 _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
640 _command[_index - 1] = 0;
65
66 // Number of documents to return
670 _command[_index++] = this.numberToReturn & 0xff;
680 _command[_index++] = (this.numberToReturn >> 8) & 0xff;
690 _command[_index++] = (this.numberToReturn >> 16) & 0xff;
700 _command[_index++] = (this.numberToReturn >> 24) & 0xff;
71
72 // Encode the cursor id
730 var low_bits = this.cursorId.getLowBits();
74 // Encode low bits
750 _command[_index++] = low_bits & 0xff;
760 _command[_index++] = (low_bits >> 8) & 0xff;
770 _command[_index++] = (low_bits >> 16) & 0xff;
780 _command[_index++] = (low_bits >> 24) & 0xff;
79
800 var high_bits = this.cursorId.getHighBits();
81 // Encode high bits
820 _command[_index++] = high_bits & 0xff;
830 _command[_index++] = (high_bits >> 8) & 0xff;
840 _command[_index++] = (high_bits >> 16) & 0xff;
850 _command[_index++] = (high_bits >> 24) & 0xff;
86 // Return command
870 return _command;
88};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/insert_command.js

7%
81
6
75
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits;
3
4/**
5 Insert Document Command
6**/
71var InsertCommand = exports.InsertCommand = function(db, collectionName, checkKeys, options) {
80 BaseCommand.call(this);
9
100 this.collectionName = collectionName;
110 this.documents = [];
120 this.checkKeys = checkKeys == null ? true : checkKeys;
130 this.db = db;
140 this.flags = 0;
150 this.serializeFunctions = false;
16
17 // Ensure valid options hash
180 options = options == null ? {} : options;
19
20 // Check if we have keepGoing set -> set flag if it's the case
210 if(options['keepGoing'] != null && options['keepGoing']) {
22 // This will finish inserting all non-index violating documents even if it returns an error
230 this.flags = 1;
24 }
25
26 // Check if we have keepGoing set -> set flag if it's the case
270 if(options['continueOnError'] != null && options['continueOnError']) {
28 // This will finish inserting all non-index violating documents even if it returns an error
290 this.flags = 1;
30 }
31
32 // Let us defined on a command basis if we want functions to be serialized or not
330 if(options['serializeFunctions'] != null && options['serializeFunctions']) {
340 this.serializeFunctions = true;
35 }
36};
37
381inherits(InsertCommand, BaseCommand);
39
40// OpCodes
411InsertCommand.OP_INSERT = 2002;
42
431InsertCommand.prototype.add = function(document) {
440 if(Buffer.isBuffer(document)) {
450 var object_size = document[0] | document[1] << 8 | document[2] << 16 | document[3] << 24;
460 if(object_size != document.length) {
470 var error = new Error("insert raw message size does not match message header size [" + document.length + "] != [" + object_size + "]");
480 error.name = 'MongoError';
490 throw error;
50 }
51 }
52
530 this.documents.push(document);
540 return this;
55};
56
57/*
58struct {
59 MsgHeader header; // standard message header
60 int32 ZERO; // 0 - reserved for future use
61 cstring fullCollectionName; // "dbname.collectionname"
62 BSON[] documents; // one or more documents to insert into the collection
63}
64*/
651InsertCommand.prototype.toBinary = function(bsonSettings) {
66 // Validate that we are not passing 0x00 in the colletion name
670 if(!!~this.collectionName.indexOf("\x00")) {
680 throw new Error("namespace cannot contain a null character");
69 }
70
71 // Calculate total length of the document
720 var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + (4 * 4);
73 // var docLength = 0
740 for(var i = 0; i < this.documents.length; i++) {
750 if(Buffer.isBuffer(this.documents[i])) {
760 totalLengthOfCommand += this.documents[i].length;
77 } else {
78 // Calculate size of document
790 totalLengthOfCommand += this.db.bson.calculateObjectSize(this.documents[i], this.serializeFunctions, true);
80 }
81 }
82
83 // Enforce maximum bson size
840 if(!bsonSettings.disableDriverBSONSizeCheck
85 && totalLengthOfCommand > bsonSettings.maxBsonSize)
860 throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
87
880 if(bsonSettings.disableDriverBSONSizeCheck
89 && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
900 throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
91
92 // Let's build the single pass buffer command
930 var _index = 0;
940 var _command = new Buffer(totalLengthOfCommand);
95 // Write the header information to the buffer
960 _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
970 _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
980 _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
990 _command[_index] = totalLengthOfCommand & 0xff;
100 // Adjust index
1010 _index = _index + 4;
102 // Write the request ID
1030 _command[_index + 3] = (this.requestId >> 24) & 0xff;
1040 _command[_index + 2] = (this.requestId >> 16) & 0xff;
1050 _command[_index + 1] = (this.requestId >> 8) & 0xff;
1060 _command[_index] = this.requestId & 0xff;
107 // Adjust index
1080 _index = _index + 4;
109 // Write zero
1100 _command[_index++] = 0;
1110 _command[_index++] = 0;
1120 _command[_index++] = 0;
1130 _command[_index++] = 0;
114 // Write the op_code for the command
1150 _command[_index + 3] = (InsertCommand.OP_INSERT >> 24) & 0xff;
1160 _command[_index + 2] = (InsertCommand.OP_INSERT >> 16) & 0xff;
1170 _command[_index + 1] = (InsertCommand.OP_INSERT >> 8) & 0xff;
1180 _command[_index] = InsertCommand.OP_INSERT & 0xff;
119 // Adjust index
1200 _index = _index + 4;
121 // Write flags if any
1220 _command[_index + 3] = (this.flags >> 24) & 0xff;
1230 _command[_index + 2] = (this.flags >> 16) & 0xff;
1240 _command[_index + 1] = (this.flags >> 8) & 0xff;
1250 _command[_index] = this.flags & 0xff;
126 // Adjust index
1270 _index = _index + 4;
128 // Write the collection name to the command
1290 _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
1300 _command[_index - 1] = 0;
131
132 // Write all the bson documents to the buffer at the index offset
1330 for(var i = 0; i < this.documents.length; i++) {
134 // Document binary length
1350 var documentLength = 0
1360 var object = this.documents[i];
137
138 // Serialize the selector
139 // If we are passing a raw buffer, do minimal validation
1400 if(Buffer.isBuffer(object)) {
1410 documentLength = object.length;
142 // Copy the data into the current buffer
1430 object.copy(_command, _index);
144 } else {
145 // Serialize the document straight to the buffer
1460 documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1;
147 }
148
149 // Write the length to the document
1500 _command[_index + 3] = (documentLength >> 24) & 0xff;
1510 _command[_index + 2] = (documentLength >> 16) & 0xff;
1520 _command[_index + 1] = (documentLength >> 8) & 0xff;
1530 _command[_index] = documentLength & 0xff;
154 // Update index in buffer
1550 _index = _index + documentLength;
156 // Add terminating 0 for the object
1570 _command[_index - 1] = 0;
158 }
159
1600 return _command;
161};
162

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js

9%
54
5
49
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits,
3 binaryutils = require('../utils');
4
5/**
6 Insert Document Command
7**/
81var KillCursorCommand = exports.KillCursorCommand = function(db, cursorIds) {
90 BaseCommand.call(this);
10
110 this.cursorIds = cursorIds;
120 this.db = db;
13};
14
151inherits(KillCursorCommand, BaseCommand);
16
171KillCursorCommand.OP_KILL_CURSORS = 2007;
18
19/*
20struct {
21 MsgHeader header; // standard message header
22 int32 ZERO; // 0 - reserved for future use
23 int32 numberOfCursorIDs; // number of cursorIDs in message
24 int64[] cursorIDs; // array of cursorIDs to close
25}
26*/
271KillCursorCommand.prototype.toBinary = function() {
28 // Calculate total length of the document
290 var totalLengthOfCommand = 4 + 4 + (4 * 4) + (this.cursorIds.length * 8);
30 // Let's build the single pass buffer command
310 var _index = 0;
320 var _command = new Buffer(totalLengthOfCommand);
33 // Write the header information to the buffer
340 _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
350 _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
360 _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
370 _command[_index] = totalLengthOfCommand & 0xff;
38 // Adjust index
390 _index = _index + 4;
40 // Write the request ID
410 _command[_index + 3] = (this.requestId >> 24) & 0xff;
420 _command[_index + 2] = (this.requestId >> 16) & 0xff;
430 _command[_index + 1] = (this.requestId >> 8) & 0xff;
440 _command[_index] = this.requestId & 0xff;
45 // Adjust index
460 _index = _index + 4;
47 // Write zero
480 _command[_index++] = 0;
490 _command[_index++] = 0;
500 _command[_index++] = 0;
510 _command[_index++] = 0;
52 // Write the op_code for the command
530 _command[_index + 3] = (KillCursorCommand.OP_KILL_CURSORS >> 24) & 0xff;
540 _command[_index + 2] = (KillCursorCommand.OP_KILL_CURSORS >> 16) & 0xff;
550 _command[_index + 1] = (KillCursorCommand.OP_KILL_CURSORS >> 8) & 0xff;
560 _command[_index] = KillCursorCommand.OP_KILL_CURSORS & 0xff;
57 // Adjust index
580 _index = _index + 4;
59
60 // Write zero
610 _command[_index++] = 0;
620 _command[_index++] = 0;
630 _command[_index++] = 0;
640 _command[_index++] = 0;
65
66 // Number of cursors to kill
670 var numberOfCursors = this.cursorIds.length;
680 _command[_index + 3] = (numberOfCursors >> 24) & 0xff;
690 _command[_index + 2] = (numberOfCursors >> 16) & 0xff;
700 _command[_index + 1] = (numberOfCursors >> 8) & 0xff;
710 _command[_index] = numberOfCursors & 0xff;
72 // Adjust index
730 _index = _index + 4;
74
75 // Encode all the cursors
760 for(var i = 0; i < this.cursorIds.length; i++) {
77 // Encode the cursor id
780 var low_bits = this.cursorIds[i].getLowBits();
79 // Encode low bits
800 _command[_index + 3] = (low_bits >> 24) & 0xff;
810 _command[_index + 2] = (low_bits >> 16) & 0xff;
820 _command[_index + 1] = (low_bits >> 8) & 0xff;
830 _command[_index] = low_bits & 0xff;
84 // Adjust index
850 _index = _index + 4;
86
870 var high_bits = this.cursorIds[i].getHighBits();
88 // Encode high bits
890 _command[_index + 3] = (high_bits >> 24) & 0xff;
900 _command[_index + 2] = (high_bits >> 16) & 0xff;
910 _command[_index + 1] = (high_bits >> 8) & 0xff;
920 _command[_index] = high_bits & 0xff;
93 // Adjust index
940 _index = _index + 4;
95 }
96
970 return _command;
98};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/query_command.js

9%
147
14
133
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits;
3
4/**
5 Insert Document Command
6**/
71var QueryCommand = exports.QueryCommand = function(db, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) {
80 BaseCommand.call(this);
9
10 // Validate correctness off the selector
110 var object = query,
12 object_size;
130 if(Buffer.isBuffer(object)) {
140 object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
150 if(object_size != object.length) {
160 var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
170 error.name = 'MongoError';
180 throw error;
19 }
20 }
21
220 object = returnFieldSelector;
230 if(Buffer.isBuffer(object)) {
240 object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
250 if(object_size != object.length) {
260 var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
270 error.name = 'MongoError';
280 throw error;
29 }
30 }
31
32 // Make sure we don't get a null exception
330 options = options == null ? {} : options;
34 // Set up options
350 this.collectionName = collectionName;
360 this.queryOptions = queryOptions;
370 this.numberToSkip = numberToSkip;
380 this.numberToReturn = numberToReturn;
39
40 // Ensure we have no null query
410 query = query == null ? {} : query;
42 // Wrap query in the $query parameter so we can add read preferences for mongos
430 this.query = query;
440 this.returnFieldSelector = returnFieldSelector;
450 this.db = db;
46
47 // Force the slave ok flag to be set if we are not using primary read preference
480 if(this.db && this.db.slaveOk) {
490 this.queryOptions |= QueryCommand.OPTS_SLAVE;
50 }
51
52 // If checkKeys set
530 this.checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : false;
54
55 // Let us defined on a command basis if we want functions to be serialized or not
560 if(options['serializeFunctions'] != null && options['serializeFunctions']) {
570 this.serializeFunctions = true;
58 }
59};
60
611inherits(QueryCommand, BaseCommand);
62
631QueryCommand.OP_QUERY = 2004;
64
65/*
66 * Adds the read prefrence to the current command
67 */
681QueryCommand.prototype.setMongosReadPreference = function(readPreference, tags) {
69 // If we have readPreference set to true set to secondary prefered
700 if(readPreference == true) {
710 readPreference = 'secondaryPreferred';
720 } else if(readPreference == 'false') {
730 readPreference = 'primary';
74 }
75
76 // Force the slave ok flag to be set if we are not using primary read preference
770 if(readPreference != false && readPreference != 'primary') {
780 this.queryOptions |= QueryCommand.OPTS_SLAVE;
79 }
80
81 // Backward compatibility, ensure $query only set on read preference so 1.8.X works
820 if((readPreference != null || tags != null) && this.query['$query'] == null) {
830 this.query = {'$query': this.query};
84 }
85
86 // If we have no readPreference set and no tags, check if the slaveOk bit is set
870 if(readPreference == null && tags == null) {
88 // If we have a slaveOk bit set the read preference for MongoS
890 if(this.queryOptions & QueryCommand.OPTS_SLAVE) {
900 this.query['$readPreference'] = {mode: 'secondary'}
91 } else {
920 this.query['$readPreference'] = {mode: 'primary'}
93 }
94 }
95
96 // Build read preference object
970 if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') {
980 this.query['$readPreference'] = readPreference.toObject();
990 } else if(readPreference != null) {
100 // Add the read preference
1010 this.query['$readPreference'] = {mode: readPreference};
102
103 // If we have tags let's add them
1040 if(tags != null) {
1050 this.query['$readPreference']['tags'] = tags;
106 }
107 }
108}
109
110/*
111struct {
112 MsgHeader header; // standard message header
113 int32 opts; // query options. See below for details.
114 cstring fullCollectionName; // "dbname.collectionname"
115 int32 numberToSkip; // number of documents to skip when returning results
116 int32 numberToReturn; // number of documents to return in the first OP_REPLY
117 BSON query ; // query object. See below for details.
118 [ BSON returnFieldSelector; ] // OPTIONAL : selector indicating the fields to return. See below for details.
119}
120*/
1211QueryCommand.prototype.toBinary = function(bsonSettings) {
122 // Validate that we are not passing 0x00 in the colletion name
1230 if(!!~this.collectionName.indexOf("\x00")) {
1240 throw new Error("namespace cannot contain a null character");
125 }
126
127 // Total length of the command
1280 var totalLengthOfCommand = 0;
129 // Calculate total length of the document
1300 if(Buffer.isBuffer(this.query)) {
1310 totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.query.length + (4 * 4);
132 } else {
1330 totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.db.bson.calculateObjectSize(this.query, this.serializeFunctions, true) + (4 * 4);
134 }
135
136 // Calculate extra fields size
1370 if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) {
1380 if(Object.keys(this.returnFieldSelector).length > 0) {
1390 totalLengthOfCommand += this.db.bson.calculateObjectSize(this.returnFieldSelector, this.serializeFunctions, true);
140 }
1410 } else if(Buffer.isBuffer(this.returnFieldSelector)) {
1420 totalLengthOfCommand += this.returnFieldSelector.length;
143 }
144
145 // Enforce maximum bson size
1460 if(!bsonSettings.disableDriverBSONSizeCheck
147 && totalLengthOfCommand > bsonSettings.maxBsonSize)
1480 throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
149
1500 if(bsonSettings.disableDriverBSONSizeCheck
151 && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
1520 throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
153
154 // Let's build the single pass buffer command
1550 var _index = 0;
1560 var _command = new Buffer(totalLengthOfCommand);
157 // Write the header information to the buffer
1580 _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
1590 _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
1600 _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
1610 _command[_index] = totalLengthOfCommand & 0xff;
162 // Adjust index
1630 _index = _index + 4;
164 // Write the request ID
1650 _command[_index + 3] = (this.requestId >> 24) & 0xff;
1660 _command[_index + 2] = (this.requestId >> 16) & 0xff;
1670 _command[_index + 1] = (this.requestId >> 8) & 0xff;
1680 _command[_index] = this.requestId & 0xff;
169 // Adjust index
1700 _index = _index + 4;
171 // Write zero
1720 _command[_index++] = 0;
1730 _command[_index++] = 0;
1740 _command[_index++] = 0;
1750 _command[_index++] = 0;
176 // Write the op_code for the command
1770 _command[_index + 3] = (QueryCommand.OP_QUERY >> 24) & 0xff;
1780 _command[_index + 2] = (QueryCommand.OP_QUERY >> 16) & 0xff;
1790 _command[_index + 1] = (QueryCommand.OP_QUERY >> 8) & 0xff;
1800 _command[_index] = QueryCommand.OP_QUERY & 0xff;
181 // Adjust index
1820 _index = _index + 4;
183
184 // Write the query options
1850 _command[_index + 3] = (this.queryOptions >> 24) & 0xff;
1860 _command[_index + 2] = (this.queryOptions >> 16) & 0xff;
1870 _command[_index + 1] = (this.queryOptions >> 8) & 0xff;
1880 _command[_index] = this.queryOptions & 0xff;
189 // Adjust index
1900 _index = _index + 4;
191
192 // Write the collection name to the command
1930 _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
1940 _command[_index - 1] = 0;
195
196 // Write the number of documents to skip
1970 _command[_index + 3] = (this.numberToSkip >> 24) & 0xff;
1980 _command[_index + 2] = (this.numberToSkip >> 16) & 0xff;
1990 _command[_index + 1] = (this.numberToSkip >> 8) & 0xff;
2000 _command[_index] = this.numberToSkip & 0xff;
201 // Adjust index
2020 _index = _index + 4;
203
204 // Write the number of documents to return
2050 _command[_index + 3] = (this.numberToReturn >> 24) & 0xff;
2060 _command[_index + 2] = (this.numberToReturn >> 16) & 0xff;
2070 _command[_index + 1] = (this.numberToReturn >> 8) & 0xff;
2080 _command[_index] = this.numberToReturn & 0xff;
209 // Adjust index
2100 _index = _index + 4;
211
212 // Document binary length
2130 var documentLength = 0
2140 var object = this.query;
215
216 // Serialize the selector
2170 if(Buffer.isBuffer(object)) {
2180 documentLength = object.length;
219 // Copy the data into the current buffer
2200 object.copy(_command, _index);
221 } else {
222 // Serialize the document straight to the buffer
2230 documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1;
224 }
225
226 // Write the length to the document
2270 _command[_index + 3] = (documentLength >> 24) & 0xff;
2280 _command[_index + 2] = (documentLength >> 16) & 0xff;
2290 _command[_index + 1] = (documentLength >> 8) & 0xff;
2300 _command[_index] = documentLength & 0xff;
231 // Update index in buffer
2320 _index = _index + documentLength;
233 // Add terminating 0 for the object
2340 _command[_index - 1] = 0;
235
236 // Push field selector if available
2370 if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) {
2380 if(Object.keys(this.returnFieldSelector).length > 0) {
2390 var documentLength = this.db.bson.serializeWithBufferAndIndex(this.returnFieldSelector, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1;
240 // Write the length to the document
2410 _command[_index + 3] = (documentLength >> 24) & 0xff;
2420 _command[_index + 2] = (documentLength >> 16) & 0xff;
2430 _command[_index + 1] = (documentLength >> 8) & 0xff;
2440 _command[_index] = documentLength & 0xff;
245 // Update index in buffer
2460 _index = _index + documentLength;
247 // Add terminating 0 for the object
2480 _command[_index - 1] = 0;
249 }
2500 } if(this.returnFieldSelector != null && Buffer.isBuffer(this.returnFieldSelector)) {
251 // Document binary length
2520 var documentLength = 0
2530 var object = this.returnFieldSelector;
254
255 // Serialize the selector
2560 documentLength = object.length;
257 // Copy the data into the current buffer
2580 object.copy(_command, _index);
259
260 // Write the length to the document
2610 _command[_index + 3] = (documentLength >> 24) & 0xff;
2620 _command[_index + 2] = (documentLength >> 16) & 0xff;
2630 _command[_index + 1] = (documentLength >> 8) & 0xff;
2640 _command[_index] = documentLength & 0xff;
265 // Update index in buffer
2660 _index = _index + documentLength;
267 // Add terminating 0 for the object
2680 _command[_index - 1] = 0;
269 }
270
271 // Return finished command
2720 return _command;
273};
274
275// Constants
2761QueryCommand.OPTS_NONE = 0;
2771QueryCommand.OPTS_TAILABLE_CURSOR = 2;
2781QueryCommand.OPTS_SLAVE = 4;
2791QueryCommand.OPTS_OPLOG_REPLAY = 8;
2801QueryCommand.OPTS_NO_CURSOR_TIMEOUT = 16;
2811QueryCommand.OPTS_AWAIT_DATA = 32;
2821QueryCommand.OPTS_EXHAUST = 64;
2831QueryCommand.OPTS_PARTIAL = 128;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/update_command.js

6%
103
7
96
LineHitsSource
11var BaseCommand = require('./base_command').BaseCommand,
2 inherits = require('util').inherits;
3
4/**
5 Update Document Command
6**/
71var UpdateCommand = exports.UpdateCommand = function(db, collectionName, spec, document, options) {
80 BaseCommand.call(this);
9
100 var object = spec;
110 if(Buffer.isBuffer(object)) {
120 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
130 if(object_size != object.length) {
140 var error = new Error("update spec raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
150 error.name = 'MongoError';
160 throw error;
17 }
18 }
19
200 var object = document;
210 if(Buffer.isBuffer(object)) {
220 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
230 if(object_size != object.length) {
240 var error = new Error("update document raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
250 error.name = 'MongoError';
260 throw error;
27 }
28 }
29
300 this.collectionName = collectionName;
310 this.spec = spec;
320 this.document = document;
330 this.db = db;
340 this.serializeFunctions = false;
350 this.checkKeys = typeof options.checkKeys != 'boolean' ? false : options.checkKeys;
36
37 // Generate correct flags
380 var db_upsert = 0;
390 var db_multi_update = 0;
400 db_upsert = options != null && options['upsert'] != null ? (options['upsert'] == true ? 1 : 0) : db_upsert;
410 db_multi_update = options != null && options['multi'] != null ? (options['multi'] == true ? 1 : 0) : db_multi_update;
42
43 // Flags
440 this.flags = parseInt(db_multi_update.toString() + db_upsert.toString(), 2);
45 // Let us defined on a command basis if we want functions to be serialized or not
460 if(options['serializeFunctions'] != null && options['serializeFunctions']) {
470 this.serializeFunctions = true;
48 }
49};
50
511inherits(UpdateCommand, BaseCommand);
52
531UpdateCommand.OP_UPDATE = 2001;
54
55/*
56struct {
57 MsgHeader header; // standard message header
58 int32 ZERO; // 0 - reserved for future use
59 cstring fullCollectionName; // "dbname.collectionname"
60 int32 flags; // bit vector. see below
61 BSON spec; // the query to select the document
62 BSON document; // the document data to update with or insert
63}
64*/
651UpdateCommand.prototype.toBinary = function(bsonSettings) {
66 // Validate that we are not passing 0x00 in the colletion name
670 if(!!~this.collectionName.indexOf("\x00")) {
680 throw new Error("namespace cannot contain a null character");
69 }
70
71 // Calculate total length of the document
720 var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.spec, false, true) +
73 this.db.bson.calculateObjectSize(this.document, this.serializeFunctions, true) + (4 * 4);
74
75 // Enforce maximum bson size
760 if(!bsonSettings.disableDriverBSONSizeCheck
77 && totalLengthOfCommand > bsonSettings.maxBsonSize)
780 throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
79
800 if(bsonSettings.disableDriverBSONSizeCheck
81 && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
820 throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
83
84 // Let's build the single pass buffer command
850 var _index = 0;
860 var _command = new Buffer(totalLengthOfCommand);
87 // Write the header information to the buffer
880 _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
890 _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
900 _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
910 _command[_index] = totalLengthOfCommand & 0xff;
92 // Adjust index
930 _index = _index + 4;
94 // Write the request ID
950 _command[_index + 3] = (this.requestId >> 24) & 0xff;
960 _command[_index + 2] = (this.requestId >> 16) & 0xff;
970 _command[_index + 1] = (this.requestId >> 8) & 0xff;
980 _command[_index] = this.requestId & 0xff;
99 // Adjust index
1000 _index = _index + 4;
101 // Write zero
1020 _command[_index++] = 0;
1030 _command[_index++] = 0;
1040 _command[_index++] = 0;
1050 _command[_index++] = 0;
106 // Write the op_code for the command
1070 _command[_index + 3] = (UpdateCommand.OP_UPDATE >> 24) & 0xff;
1080 _command[_index + 2] = (UpdateCommand.OP_UPDATE >> 16) & 0xff;
1090 _command[_index + 1] = (UpdateCommand.OP_UPDATE >> 8) & 0xff;
1100 _command[_index] = UpdateCommand.OP_UPDATE & 0xff;
111 // Adjust index
1120 _index = _index + 4;
113
114 // Write zero
1150 _command[_index++] = 0;
1160 _command[_index++] = 0;
1170 _command[_index++] = 0;
1180 _command[_index++] = 0;
119
120 // Write the collection name to the command
1210 _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
1220 _command[_index - 1] = 0;
123
124 // Write the update flags
1250 _command[_index + 3] = (this.flags >> 24) & 0xff;
1260 _command[_index + 2] = (this.flags >> 16) & 0xff;
1270 _command[_index + 1] = (this.flags >> 8) & 0xff;
1280 _command[_index] = this.flags & 0xff;
129 // Adjust index
1300 _index = _index + 4;
131
132 // Document binary length
1330 var documentLength = 0
1340 var object = this.spec;
135
136 // Serialize the selector
137 // If we are passing a raw buffer, do minimal validation
1380 if(Buffer.isBuffer(object)) {
1390 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
1400 if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
1410 documentLength = object.length;
142 // Copy the data into the current buffer
1430 object.copy(_command, _index);
144 } else {
1450 documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, false) - _index + 1;
146 }
147
148 // Write the length to the document
1490 _command[_index + 3] = (documentLength >> 24) & 0xff;
1500 _command[_index + 2] = (documentLength >> 16) & 0xff;
1510 _command[_index + 1] = (documentLength >> 8) & 0xff;
1520 _command[_index] = documentLength & 0xff;
153 // Update index in buffer
1540 _index = _index + documentLength;
155 // Add terminating 0 for the object
1560 _command[_index - 1] = 0;
157
158 // Document binary length
1590 var documentLength = 0
1600 var object = this.document;
161
162 // Serialize the document
163 // If we are passing a raw buffer, do minimal validation
1640 if(Buffer.isBuffer(object)) {
1650 var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
1660 if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
1670 documentLength = object.length;
168 // Copy the data into the current buffer
1690 object.copy(_command, _index);
170 } else {
1710 documentLength = this.db.bson.serializeWithBufferAndIndex(object, false, _command, _index, this.serializeFunctions) - _index + 1;
172 }
173
174 // Write the length to the document
1750 _command[_index + 3] = (documentLength >> 24) & 0xff;
1760 _command[_index + 2] = (documentLength >> 16) & 0xff;
1770 _command[_index + 1] = (documentLength >> 8) & 0xff;
1780 _command[_index] = documentLength & 0xff;
179 // Update index in buffer
1800 _index = _index + documentLength;
181 // Add terminating 0 for the object
1820 _command[_index - 1] = 0;
183
1840 return _command;
185};
186
187// Constants
1881UpdateCommand.DB_UPSERT = 0;
1891UpdateCommand.DB_MULTI_UPDATE = 1;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js

30%
196
60
136
LineHitsSource
11var EventEmitter = require('events').EventEmitter
2 , inherits = require('util').inherits
3 , utils = require('../utils')
4 , mongodb_cr_authenticate = require('../auth/mongodb_cr.js').authenticate
5 , mongodb_gssapi_authenticate = require('../auth/mongodb_gssapi.js').authenticate
6 , mongodb_sspi_authenticate = require('../auth/mongodb_sspi.js').authenticate
7 , mongodb_plain_authenticate = require('../auth/mongodb_plain.js').authenticate
8 , mongodb_x509_authenticate = require('../auth/mongodb_x509.js').authenticate;
9
101var id = 0;
11
12/**
13 * Internal class for callback storage
14 * @ignore
15 */
161var CallbackStore = function() {
17 // Make class an event emitter
182 EventEmitter.call(this);
19 // Add a info about call variable
202 this._notReplied = {};
212 this.id = id++;
22}
23
24/**
25 * @ignore
26 */
271inherits(CallbackStore, EventEmitter);
28
291CallbackStore.prototype.notRepliedToIds = function() {
300 return Object.keys(this._notReplied);
31}
32
331CallbackStore.prototype.callbackInfo = function(id) {
340 return this._notReplied[id];
35}
36
37/**
38 * Internal class for holding non-executed commands
39 * @ignore
40 */
411var NonExecutedOperationStore = function(config) {
421 var commands = {
43 read: []
44 , write_reads: []
45 , write: []
46 };
47
48 // Execute all callbacks
491 var fireCallbacksWithError = function(error, commands) {
500 while(commands.length > 0) {
510 var command = commands.shift();
520 if(typeof command.callback == 'function') {
530 command.callback(error);
54 }
55 }
56 }
57
581 this.count = function() {
590 return commands.read.length
60 + commands.write_reads.length
61 + commands.write.length;
62 }
63
641 this.write = function(op) {
650 commands.write.push(op);
66 }
67
681 this.read_from_writer = function(op) {
690 commands.write_reads.push(op);
70 }
71
721 this.read = function(op) {
730 commands.read.push(op);
74 }
75
761 this.validateBufferLimit = function(numberToFailOn) {
770 if(numberToFailOn == -1 || numberToFailOn == null)
780 return true;
79
80 // Error passed back
810 var error = utils.toError("No connection operations buffering limit of " + numberToFailOn + " reached");
82
83 // If we have passed the number of items to buffer we need to fail
840 if(numberToFailOn < this.count()) {
85 // Fail all of the callbacks
860 fireCallbacksWithError(error, commands.read);
870 fireCallbacksWithError(error, commands.write_reads);
880 fireCallbacksWithError(error, commands.write);
89 }
90
91 // Return false
920 return false;
93 }
94
951 this.execute_queries = function(executeInsertCommand) {
960 var connection = config.checkoutReader();
970 if(connection == null || connection instanceof Error) return;
98
99 // Write out all the queries
1000 while(commands.read.length > 0) {
101 // Get the next command
1020 var command = commands.read.shift();
1030 command.options.connection = connection;
104 // Execute the next command
1050 command.executeQueryCommand(command.db, command.db_command, command.options, command.callback);
106 }
107 }
108
1091 this.execute_writes = function() {
1100 var connection = config.checkoutWriter();
1110 if(connection == null || connection instanceof Error) return;
112
113 // Write out all the queries to the primary
1140 while(commands.write_reads.length > 0) {
115 // Get the next command
1160 var command = commands.write_reads.shift();
1170 command.options.connection = connection;
118 // Execute the next command
1190 command.executeQueryCommand(command.db, command.db_command, command.options, command.callback);
120 }
121
122 // Execute all write operations
1230 while(commands.write.length > 0) {
124 // Get the next command
1250 var command = commands.write.shift();
126 // Set the connection
1270 command.options.connection = connection;
128 // Execute the next command
1290 command.executeInsertCommand(command.db, command.db_command, command.options, command.callback);
130 }
131 }
132}
133
134/**
135 * Internal class for authentication storage
136 * @ignore
137 */
1381var AuthStore = function() {
1391 var _auths = [];
140
1411 this.add = function(authMechanism, dbName, username, password, authdbName, gssapiServiceName) {
142 // Check for duplicates
1430 if(!this.contains(dbName)) {
144 // Base config
1450 var config = {
146 'username':username
147 , 'password':password
148 , 'db': dbName
149 , 'authMechanism': authMechanism
150 , 'gssapiServiceName': gssapiServiceName
151 };
152
153 // Add auth source if passed in
1540 if(typeof authdbName == 'string') {
1550 config['authdb'] = authdbName;
156 }
157
158 // Push the config
1590 _auths.push(config);
160 }
161 }
162
1631 this.contains = function(dbName) {
1640 for(var i = 0; i < _auths.length; i++) {
1650 if(_auths[i].db == dbName) return true;
166 }
167
1680 return false;
169 }
170
1711 this.remove = function(dbName) {
1720 var newAuths = [];
173
174 // Filter out all the login details
1750 for(var i = 0; i < _auths.length; i++) {
1760 if(_auths[i].db != dbName) newAuths.push(_auths[i]);
177 }
178
179 // Set the filtered list
1800 _auths = newAuths;
181 }
182
1831 this.get = function(index) {
1840 return _auths[index];
185 }
186
1871 this.length = function() {
1880 return _auths.length;
189 }
190
1911 this.toArray = function() {
1920 return _auths.slice(0);
193 }
194}
195
196/**
197 * Internal class for storing db references
198 * @ignore
199 */
2001var DbStore = function() {
2011 var _dbs = [];
202
2031 this.add = function(db) {
2041 var found = false;
205
206 // Only add if it does not exist already
2071 for(var i = 0; i < _dbs.length; i++) {
2080 if(db.databaseName == _dbs[i].databaseName) found = true;
209 }
210
211 // Only add if it does not already exist
2121 if(!found) {
2131 _dbs.push(db);
214 }
215 }
216
2171 this.reset = function() {
2180 _dbs = [];
219 }
220
2211 this.db = function() {
2220 return _dbs;
223 }
224
2251 this.fetch = function(databaseName) {
226 // Only add if it does not exist already
2270 for(var i = 0; i < _dbs.length; i++) {
2280 if(databaseName == _dbs[i].databaseName)
2290 return _dbs[i];
230 }
231
2320 return null;
233 }
234
2351 this.emit = function(event, message, object, reset, filterDb, rethrow_if_no_listeners) {
2360 var emitted = false;
237
238 // Not emitted and we have enabled rethrow, let process.uncaughtException
239 // deal with the issue
2400 if(!emitted && rethrow_if_no_listeners) {
2410 return process.nextTick(function() {
2420 throw message;
243 })
244 }
245
246 // Emit the events
2470 for(var i = 0; i < _dbs.length; i++) {
2480 if(_dbs[i].listeners(event).length > 0) {
2490 if(filterDb == null || filterDb.databaseName !== _dbs[i].databaseName
250 || filterDb.tag !== _dbs[i].tag) {
2510 _dbs[i].emit(event, message, object == null ? _dbs[i] : object);
2520 emitted = true;
253 }
254 }
255 }
256
257 // Emit error message
2580 if(message
259 && event == 'error'
260 && !emitted
261 && rethrow_if_no_listeners
262 && object && object.db) {
2630 process.nextTick(function() {
2640 object.db.emit(event, message, null);
265 })
266 }
267 }
268}
269
2701var Base = function Base() {
2711 EventEmitter.call(this);
272
273 // Callback store is part of connection specification
2741 if(Base._callBackStore == null) {
2751 Base._callBackStore = new CallbackStore();
276 }
277
278 // Create a new callback store
2791 this._callBackStore = new CallbackStore();
280 // All commands not being executed
2811 this._commandsStore = new NonExecutedOperationStore(this);
282 // Create a new auth store
2831 this.auth = new AuthStore();
284 // Contains all the dbs attached to this server config
2851 this._dbStore = new DbStore();
286}
287
288/**
289 * @ignore
290 */
2911inherits(Base, EventEmitter);
292
293/**
294 * @ignore
295 */
2961Base.prototype._apply_auths = function(db, callback) {
2970 _apply_auths_serially(this, db, this.auth.toArray(), callback);
298}
299
3001var _apply_auths_serially = function(self, db, auths, callback) {
3010 if(auths.length == 0) return callback(null, null);
302 // Get the first auth
3030 var auth = auths.shift();
3040 var connections = self.allRawConnections();
3050 var connectionsLeft = connections.length;
3060 var options = {};
307
3080 if(auth.authMechanism == 'GSSAPI') {
309 // We have the kerberos library, execute auth process
3100 if(process.platform == 'win32') {
3110 mongodb_sspi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
312 } else {
3130 mongodb_gssapi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
314 }
3150 } else if(auth.authMechanism == 'MONGODB-CR') {
3160 mongodb_cr_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
3170 } else if(auth.authMechanism == 'PLAIN') {
3180 mongodb_plain_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
3190 } else if(auth.authMechanism == 'MONGODB-X509') {
3200 mongodb_x509_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
321 }
322}
323
324/**
325 * Fire all the errors
326 * @ignore
327 */
3281Base.prototype.__executeAllCallbacksWithError = function(err) {
329 // Check all callbacks
3300 var keys = Object.keys(this._callBackStore._notReplied);
331 // For each key check if it's a callback that needs to be returned
3320 for(var j = 0; j < keys.length; j++) {
3330 var info = this._callBackStore._notReplied[keys[j]];
334 // Execute callback with error
3350 this._callBackStore.emit(keys[j], err, null);
336 // Remove the key
3370 delete this._callBackStore._notReplied[keys[j]];
338 // Force cleanup _events, node.js seems to set it as a null value
3390 if(this._callBackStore._events) {
3400 delete this._callBackStore._events[keys[j]];
341 }
342 }
343}
344
345/**
346 * Fire all the errors
347 * @ignore
348 */
3491Base.prototype.__executeAllServerSpecificErrorCallbacks = function(host, port, err) {
350 // Check all callbacks
3510 var keys = Object.keys(this._callBackStore._notReplied);
352 // For each key check if it's a callback that needs to be returned
3530 for(var j = 0; j < keys.length; j++) {
3540 var info = this._callBackStore._notReplied[keys[j]];
355
3560 if(info.connection) {
357 // Unpack the connection settings
3580 var _host = info.connection.socketOptions.host;
3590 var _port = info.connection.socketOptions.port;
360 // If the server matches execute the callback with the error
3610 if(_port == port && _host == host) {
3620 this._callBackStore.emit(keys[j], err, null);
363 // Remove the key
3640 delete this._callBackStore._notReplied[keys[j]];
365 // Force cleanup _events, node.js seems to set it as a null value
3660 if(this._callBackStore._events) {
3670 delete this._callBackStore._events[keys[j]];
368 }
369 }
370 }
371 }
372}
373
374/**
375 * Register a handler
376 * @ignore
377 * @api private
378 */
3791Base.prototype._registerHandler = function(db_command, raw, connection, exhaust, callback) {
380 // Check if we have exhausted
3810 if(typeof exhaust == 'function') {
3820 callback = exhaust;
3830 exhaust = false;
384 }
385
386 // Add the callback to the list of handlers
3870 this._callBackStore.once(db_command.getRequestId(), callback);
388 // Add the information about the reply
3890 this._callBackStore._notReplied[db_command.getRequestId().toString()] = {start: new Date().getTime(), 'raw': raw, connection:connection, exhaust:exhaust};
390}
391
392/**
393 * Re-Register a handler, on the cursor id f.ex
394 * @ignore
395 * @api private
396 */
3971Base.prototype._reRegisterHandler = function(newId, object, callback) {
398 // Add the callback to the list of handlers
3990 this._callBackStore.once(newId, object.callback.listener);
400 // Add the information about the reply
4010 this._callBackStore._notReplied[newId] = object.info;
402}
403
404/**
405 *
406 * @ignore
407 * @api private
408 */
4091Base.prototype._flushAllCallHandlers = function(err) {
4100 var keys = Object.keys(this._callBackStore._notReplied);
411
4120 for(var i = 0; i < keys.length; i++) {
4130 this._callHandler(keys[i], null, err);
414 }
415}
416
417/**
418 *
419 * @ignore
420 * @api private
421 */
4221Base.prototype._callHandler = function(id, document, err) {
4230 var self = this;
424
425 // If there is a callback peform it
4260 if(this._callBackStore.listeners(id).length >= 1) {
427 // Get info object
4280 var info = this._callBackStore._notReplied[id];
429 // Delete the current object
4300 delete this._callBackStore._notReplied[id];
431 // Call the handle directly don't emit
4320 var callback = this._callBackStore.listeners(id)[0].listener;
433 // Remove the listeners
4340 this._callBackStore.removeAllListeners(id);
435 // Force key deletion because it nulling it not deleting in 0.10.X
4360 if(this._callBackStore._events) {
4370 delete this._callBackStore._events[id];
438 }
439
4400 try {
441 // Execute the callback if one was provided
4420 if(typeof callback == 'function') callback(err, document, info.connection);
443 } catch(err) {
4440 self._emitAcrossAllDbInstances(self, null, "error", utils.toError(err), self, true, true);
445 }
446 }
447}
448
449/**
450 *
451 * @ignore
452 * @api private
453 */
4541Base.prototype._hasHandler = function(id) {
4550 return this._callBackStore.listeners(id).length >= 1;
456}
457
458/**
459 *
460 * @ignore
461 * @api private
462 */
4631Base.prototype._removeHandler = function(id) {
464 // Remove the information
4650 if(this._callBackStore._notReplied[id] != null) delete this._callBackStore._notReplied[id];
466 // Remove the callback if it's registered
4670 this._callBackStore.removeAllListeners(id);
468 // Force cleanup _events, node.js seems to set it as a null value
4690 if(this._callBackStore._events) {
4700 delete this._callBackStore._events[id];
471 }
472}
473
474/**
475 *
476 * @ignore
477 * @api private
478 */
4791Base.prototype._findHandler = function(id) {
4800 var info = this._callBackStore._notReplied[id];
481 // Return the callback
4820 return {info:info, callback:(this._callBackStore.listeners(id).length >= 1) ? this._callBackStore.listeners(id)[0] : null}
483}
484
485/**
486 *
487 * @ignore
488 * @api private
489 */
4901Base.prototype._emitAcrossAllDbInstances = function(server, filterDb, event, message, object, resetConnection, rethrow_if_no_listeners) {
4910 if(resetConnection) {
4920 var dbs = this._dbStore.db();
493
4940 for(var i = 0; i < dbs.length; i++) {
4950 if(typeof dbs[i].openCalled != 'undefined')
4960 dbs[i].openCalled = false;
497 }
498 }
499
500 // Fire event
5010 this._dbStore.emit(event, message, object, resetConnection, filterDb, rethrow_if_no_listeners);
502}
503
5041exports.Base = Base;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js

27%
233
63
170
LineHitsSource
11var utils = require('./connection_utils'),
2 inherits = require('util').inherits,
3 net = require('net'),
4 EventEmitter = require('events').EventEmitter,
5 inherits = require('util').inherits,
6 binaryutils = require('../utils'),
7 tls = require('tls');
8
91var Connection = exports.Connection = function(id, socketOptions) {
101 var self = this;
11 // Set up event emitter
121 EventEmitter.call(this);
13 // Store all socket options
141 this.socketOptions = socketOptions ? socketOptions : {host:'localhost', port:27017, domainSocket:false};
15 // Set keep alive default if not overriden
161 if(this.socketOptions.keepAlive == null && (process.platform !== "sunos" || process.platform !== "win32")) this.socketOptions.keepAlive = 100;
17 // Id for the connection
181 this.id = id;
19 // State of the connection
201 this.connected = false;
21 // Set if this is a domain socket
221 this.domainSocket = this.socketOptions.domainSocket;
23
24 // Supported min and max wire protocol
251 this.minWireVersion = 0;
261 this.maxWireVersion = 2;
27
28 //
29 // Connection parsing state
30 //
311 this.maxBsonSize = socketOptions.maxBsonSize ? socketOptions.maxBsonSize : Connection.DEFAULT_MAX_BSON_SIZE;
321 this.maxMessageSizeBytes = socketOptions.maxMessageSizeBytes ? socketOptions.maxMessageSizeBytes : Connection.DEFAULT_MAX_MESSAGE_SIZE;
33 // Contains the current message bytes
341 this.buffer = null;
35 // Contains the current message size
361 this.sizeOfMessage = 0;
37 // Contains the readIndex for the messaage
381 this.bytesRead = 0;
39 // Contains spill over bytes from additional messages
401 this.stubBuffer = 0;
41
42 // Just keeps list of events we allow
431 this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[], end:[]};
44
45 // Just keeps list of events we allow
461 resetHandlers(this, false);
47 // Bson object
481 this.maxBsonSettings = {
49 disableDriverBSONSizeCheck: this.socketOptions['disableDriverBSONSizeCheck'] || false
50 , maxBsonSize: this.maxBsonSize
51 , maxMessageSizeBytes: this.maxMessageSizeBytes
52 }
53
54 // Allow setting the socketTimeoutMS on all connections
55 // to work around issues such as secondaries blocking due to compaction
561 Object.defineProperty(this, "socketTimeoutMS", {
57 enumerable: true
580 , get: function () { return self.socketOptions.socketTimeoutMS; }
59 , set: function (value) {
60 // Set the socket timeoutMS value
610 self.socketOptions.socketTimeoutMS = value;
62 // Set the physical connection timeout
630 self.connection.setTimeout(self.socketOptions.socketTimeoutMS);
64 }
65 });
66}
67
68// Set max bson size
691Connection.DEFAULT_MAX_BSON_SIZE = 1024 * 1024 * 4;
70// Set default to max bson to avoid overflow or bad guesses
711Connection.DEFAULT_MAX_MESSAGE_SIZE = Connection.DEFAULT_MAX_BSON_SIZE;
72
73// Inherit event emitter so we can emit stuff wohoo
741inherits(Connection, EventEmitter);
75
761Connection.prototype.start = function() {
771 var self = this;
78
79 // If we have a normal connection
801 if(this.socketOptions.ssl) {
81 // Create new connection instance
820 if(this.domainSocket) {
830 this.connection = net.createConnection(this.socketOptions.host);
84 } else {
850 this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host);
86 }
870 if(this.logger != null && this.logger.doDebug){
880 this.logger.debug("opened connection", this.socketOptions);
89 }
90
91 // Set options on the socket
920 this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout);
93 // Work around for 0.4.X
940 if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay);
95 // Set keep alive if defined
960 if(process.version.indexOf("v0.4") == -1) {
970 if(this.socketOptions.keepAlive > 0) {
980 this.connection.setKeepAlive(true, this.socketOptions.keepAlive);
99 } else {
1000 this.connection.setKeepAlive(false);
101 }
102 }
103
104 // Check if the driver should validate the certificate
1050 var validate_certificates = this.socketOptions.sslValidate == true ? true : false;
106
107 // Create options for the tls connection
1080 var tls_options = {
109 socket: this.connection
110 , rejectUnauthorized: false
111 }
112
113 // If we wish to validate the certificate we have provided a ca store
1140 if(validate_certificates) {
1150 tls_options.ca = this.socketOptions.sslCA;
116 }
117
118 // If we have a certificate to present
1190 if(this.socketOptions.sslCert) {
1200 tls_options.cert = this.socketOptions.sslCert;
1210 tls_options.key = this.socketOptions.sslKey;
122 }
123
124 // If the driver has been provided a private key password
1250 if(this.socketOptions.sslPass) {
1260 tls_options.passphrase = this.socketOptions.sslPass;
127 }
128
129 // Contains the cleartext stream
1300 var cleartext = null;
131 // Attempt to establish a TLS connection to the server
1320 try {
1330 cleartext = tls.connect(this.socketOptions.port, this.socketOptions.host, tls_options, function() {
134 // If we have a ssl certificate validation error return an error
1350 if(cleartext.authorizationError && validate_certificates) {
136 // Emit an error
1370 return self.emit("error", cleartext.authorizationError, self, {ssl:true});
138 }
139
140 // Connect to the server
1410 connectHandler(self)();
142 })
143 } catch(err) {
1440 return self.emit("error", "SSL connection failed", self, {ssl:true});
145 }
146
147 // Save the output stream
1480 this.writeSteam = cleartext;
149
150 // Set up data handler for the clear stream
1510 cleartext.on("data", createDataHandler(this));
152 // Do any handling of end event of the stream
1530 cleartext.on("end", endHandler(this));
1540 cleartext.on("error", errorHandler(this));
155
156 // Handle any errors
1570 this.connection.on("error", errorHandler(this));
158 // Handle timeout
1590 this.connection.on("timeout", timeoutHandler(this));
160 // Handle drain event
1610 this.connection.on("drain", drainHandler(this));
162 // Handle the close event
1630 this.connection.on("close", closeHandler(this));
164 } else {
165 // Create new connection instance
1661 if(this.domainSocket) {
1670 this.connection = net.createConnection(this.socketOptions.host);
168 } else {
1691 this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host);
170 }
1711 if(this.logger != null && this.logger.doDebug){
1720 this.logger.debug("opened connection", this.socketOptions);
173 }
174
175 // Set options on the socket
1761 this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout);
177 // Work around for 0.4.X
1782 if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay);
179 // Set keep alive if defined
1801 if(process.version.indexOf("v0.4") == -1) {
1811 if(this.socketOptions.keepAlive > 0) {
1820 this.connection.setKeepAlive(true, this.socketOptions.keepAlive);
183 } else {
1841 this.connection.setKeepAlive(false);
185 }
186 }
187
188 // Set up write stream
1891 this.writeSteam = this.connection;
190 // Add handlers
1911 this.connection.on("error", errorHandler(this));
192 // Add all handlers to the socket to manage it
1931 this.connection.on("connect", connectHandler(this));
194 // this.connection.on("end", endHandler(this));
1951 this.connection.on("data", createDataHandler(this));
1961 this.connection.on("timeout", timeoutHandler(this));
1971 this.connection.on("drain", drainHandler(this));
1981 this.connection.on("close", closeHandler(this));
199 }
200}
201
202// Check if the sockets are live
2031Connection.prototype.isConnected = function() {
2040 return this.connected && !this.connection.destroyed && this.connection.writable && this.connection.readable;
205}
206
207// Validate if the driver supports this server
2081Connection.prototype.isCompatible = function() {
2090 if(this.serverCapabilities == null) return true;
210 // Is compatible with backward server
2110 if(this.serverCapabilities.minWireVersion == 0
2120 && this.serverCapabilities.maxWireVersion ==0) return true;
213
214 // Check if we overlap
2150 if(this.serverCapabilities.minWireVersion >= this.minWireVersion
2160 && this.serverCapabilities.maxWireVersion <= this.maxWireVersion) return true;
217
218 // Not compatible
2190 return false;
220}
221
222// Write the data out to the socket
2231Connection.prototype.write = function(command, callback) {
2240 try {
225 // If we have a list off commands to be executed on the same socket
2260 if(Array.isArray(command)) {
2270 for(var i = 0; i < command.length; i++) {
2280 try {
229 // Pass in the bson validation settings (validate early)
2300 var binaryCommand = command[i].toBinary(this.maxBsonSettings)
231
2320 if(this.logger != null && this.logger.doDebug)
2330 this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command[i]});
234
2350 this.writeSteam.write(binaryCommand);
236 } catch(err) {
2370 return callback(err, null);
238 }
239 }
240 } else {
2410 try {
242 // Pass in the bson validation settings (validate early)
2430 var binaryCommand = command.toBinary(this.maxBsonSettings)
244 // Do we have a logger active log the event
2450 if(this.logger != null && this.logger.doDebug)
2460 this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command[i]});
247 // Write the binary command out to socket
2480 this.writeSteam.write(binaryCommand);
249 } catch(err) {
2500 return callback(err, null)
251 }
252 }
253 } catch (err) {
2540 if(typeof callback === 'function') callback(err);
255 }
256}
257
258// Force the closure of the connection
2591Connection.prototype.close = function() {
260 // clear out all the listeners
2610 resetHandlers(this, true);
262 // Add a dummy error listener to catch any weird last moment errors (and ignore them)
2630 this.connection.on("error", function() {})
264 // destroy connection
2650 this.connection.destroy();
2660 if(this.logger != null && this.logger.doDebug){
2670 this.logger.debug("closed connection", this.connection);
268 }
269}
270
271// Reset all handlers
2721var resetHandlers = function(self, clearListeners) {
2731 self.eventHandlers = {error:[], connect:[], close:[], end:[], timeout:[], parseError:[], message:[]};
274
275 // If we want to clear all the listeners
2761 if(clearListeners && self.connection != null) {
2770 var keys = Object.keys(self.eventHandlers);
278 // Remove all listeners
2790 for(var i = 0; i < keys.length; i++) {
2800 self.connection.removeAllListeners(keys[i]);
281 }
282 }
283}
284
285//
286// Handlers
287//
288
289// Connect handler
2901var connectHandler = function(self) {
2911 return function(data) {
292 // Set connected
2930 self.connected = true;
294 // Now that we are connected set the socket timeout
2950 self.connection.setTimeout(self.socketOptions.socketTimeoutMS != null ? self.socketOptions.socketTimeoutMS : self.socketOptions.timeout);
296 // Emit the connect event with no error
2970 self.emit("connect", null, self);
298 }
299}
300
3011var createDataHandler = exports.Connection.createDataHandler = function(self) {
302 // We need to handle the parsing of the data
303 // and emit the messages when there is a complete one
3041 return function(data) {
305 // Parse until we are done with the data
3060 while(data.length > 0) {
307 // If we still have bytes to read on the current message
3080 if(self.bytesRead > 0 && self.sizeOfMessage > 0) {
309 // Calculate the amount of remaining bytes
3100 var remainingBytesToRead = self.sizeOfMessage - self.bytesRead;
311 // Check if the current chunk contains the rest of the message
3120 if(remainingBytesToRead > data.length) {
313 // Copy the new data into the exiting buffer (should have been allocated when we know the message size)
3140 data.copy(self.buffer, self.bytesRead);
315 // Adjust the number of bytes read so it point to the correct index in the buffer
3160 self.bytesRead = self.bytesRead + data.length;
317
318 // Reset state of buffer
3190 data = new Buffer(0);
320 } else {
321 // Copy the missing part of the data into our current buffer
3220 data.copy(self.buffer, self.bytesRead, 0, remainingBytesToRead);
323 // Slice the overflow into a new buffer that we will then re-parse
3240 data = data.slice(remainingBytesToRead);
325
326 // Emit current complete message
3270 try {
3280 var emitBuffer = self.buffer;
329 // Reset state of buffer
3300 self.buffer = null;
3310 self.sizeOfMessage = 0;
3320 self.bytesRead = 0;
3330 self.stubBuffer = null;
334 // Emit the buffer
3350 self.emit("message", emitBuffer, self);
336 } catch(err) {
3370 var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
338 sizeOfMessage:self.sizeOfMessage,
339 bytesRead:self.bytesRead,
340 stubBuffer:self.stubBuffer}};
3410 if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
342 // We got a parse Error fire it off then keep going
3430 self.emit("parseError", errorObject, self);
344 }
345 }
346 } else {
347 // Stub buffer is kept in case we don't get enough bytes to determine the
348 // size of the message (< 4 bytes)
3490 if(self.stubBuffer != null && self.stubBuffer.length > 0) {
350
351 // If we have enough bytes to determine the message size let's do it
3520 if(self.stubBuffer.length + data.length > 4) {
353 // Prepad the data
3540 var newData = new Buffer(self.stubBuffer.length + data.length);
3550 self.stubBuffer.copy(newData, 0);
3560 data.copy(newData, self.stubBuffer.length);
357 // Reassign for parsing
3580 data = newData;
359
360 // Reset state of buffer
3610 self.buffer = null;
3620 self.sizeOfMessage = 0;
3630 self.bytesRead = 0;
3640 self.stubBuffer = null;
365
366 } else {
367
368 // Add the the bytes to the stub buffer
3690 var newStubBuffer = new Buffer(self.stubBuffer.length + data.length);
370 // Copy existing stub buffer
3710 self.stubBuffer.copy(newStubBuffer, 0);
372 // Copy missing part of the data
3730 data.copy(newStubBuffer, self.stubBuffer.length);
374 // Exit parsing loop
3750 data = new Buffer(0);
376 }
377 } else {
3780 if(data.length > 4) {
379 // Retrieve the message size
3800 var sizeOfMessage = binaryutils.decodeUInt32(data, 0);
381 // If we have a negative sizeOfMessage emit error and return
3820 if(sizeOfMessage < 0 || sizeOfMessage > self.maxBsonSize) {
3830 var errorObject = {err:"socketHandler", trace:'', bin:self.buffer, parseState:{
384 sizeOfMessage: sizeOfMessage,
385 bytesRead: self.bytesRead,
386 stubBuffer: self.stubBuffer}};
3870 if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
388 // We got a parse Error fire it off then keep going
3890 self.emit("parseError", errorObject, self);
3900 return;
391 }
392
393 // Ensure that the size of message is larger than 0 and less than the max allowed
3940 if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage > data.length) {
3950 self.buffer = new Buffer(sizeOfMessage);
396 // Copy all the data into the buffer
3970 data.copy(self.buffer, 0);
398 // Update bytes read
3990 self.bytesRead = data.length;
400 // Update sizeOfMessage
4010 self.sizeOfMessage = sizeOfMessage;
402 // Ensure stub buffer is null
4030 self.stubBuffer = null;
404 // Exit parsing loop
4050 data = new Buffer(0);
406
4070 } else if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage == data.length) {
4080 try {
4090 var emitBuffer = data;
410 // Reset state of buffer
4110 self.buffer = null;
4120 self.sizeOfMessage = 0;
4130 self.bytesRead = 0;
4140 self.stubBuffer = null;
415 // Exit parsing loop
4160 data = new Buffer(0);
417 // Emit the message
4180 self.emit("message", emitBuffer, self);
419 } catch (err) {
4200 var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
421 sizeOfMessage:self.sizeOfMessage,
422 bytesRead:self.bytesRead,
423 stubBuffer:self.stubBuffer}};
4240 if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
425 // We got a parse Error fire it off then keep going
4260 self.emit("parseError", errorObject, self);
427 }
4280 } else if(sizeOfMessage <= 4 || sizeOfMessage > self.maxBsonSize) {
4290 var errorObject = {err:"socketHandler", trace:null, bin:data, parseState:{
430 sizeOfMessage:sizeOfMessage,
431 bytesRead:0,
432 buffer:null,
433 stubBuffer:null}};
4340 if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
435 // We got a parse Error fire it off then keep going
4360 self.emit("parseError", errorObject, self);
437
438 // Clear out the state of the parser
4390 self.buffer = null;
4400 self.sizeOfMessage = 0;
4410 self.bytesRead = 0;
4420 self.stubBuffer = null;
443 // Exit parsing loop
4440 data = new Buffer(0);
445
446 } else {
4470 try {
4480 var emitBuffer = data.slice(0, sizeOfMessage);
449 // Reset state of buffer
4500 self.buffer = null;
4510 self.sizeOfMessage = 0;
4520 self.bytesRead = 0;
4530 self.stubBuffer = null;
454 // Copy rest of message
4550 data = data.slice(sizeOfMessage);
456 // Emit the message
4570 self.emit("message", emitBuffer, self);
458 } catch (err) {
4590 var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
460 sizeOfMessage:sizeOfMessage,
461 bytesRead:self.bytesRead,
462 stubBuffer:self.stubBuffer}};
4630 if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
464 // We got a parse Error fire it off then keep going
4650 self.emit("parseError", errorObject, self);
466 }
467
468 }
469 } else {
470 // Create a buffer that contains the space for the non-complete message
4710 self.stubBuffer = new Buffer(data.length)
472 // Copy the data to the stub buffer
4730 data.copy(self.stubBuffer, 0);
474 // Exit parsing loop
4750 data = new Buffer(0);
476 }
477 }
478 }
479 }
480 }
481}
482
4831var endHandler = function(self) {
4840 return function() {
485 // Set connected to false
4860 self.connected = false;
487 // Emit end event
4880 self.emit("end", {err: 'connection received Fin packet from [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
489 }
490}
491
4921var timeoutHandler = function(self) {
4931 return function() {
494 // Set connected to false
4950 self.connected = false;
496 // Emit timeout event
4970 self.emit("timeout", {err: 'connection to [' + self.socketOptions.host + ':' + self.socketOptions.port + '] timed out'}, self);
498 }
499}
500
5011var drainHandler = function(self) {
5021 return function() {
503 }
504}
505
5061var errorHandler = function(self) {
5071 return function(err) {
5080 self.connection.destroy();
509 // Set connected to false
5100 self.connected = false;
511 // Emit error
5120 self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
513 }
514}
515
5161var closeHandler = function(self) {
5171 return function(hadError) {
518 // If we have an error during the connection phase
5190 if(hadError && !self.connected) {
520 // Set disconnected
5210 self.connected = false;
522 // Emit error
5230 self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
524 } else {
525 // Set disconnected
5260 self.connected = false;
527 // Emit close
5280 self.emit("close", {err: 'connection closed to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
529 }
530 }
531}
532
533// Some basic defaults
5341Connection.DEFAULT_PORT = 27017;
535
536
537
538
539
540
541
542

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js

42%
124
53
71
LineHitsSource
11var utils = require('./connection_utils'),
2 inherits = require('util').inherits,
3 net = require('net'),
4 timers = require('timers'),
5 EventEmitter = require('events').EventEmitter,
6 inherits = require('util').inherits,
7 MongoReply = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/../responses/mongo_reply").MongoReply,
8 Connection = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/./connection").Connection;
9
10// Set processor, setImmediate if 0.10 otherwise nextTick
111var processor = require('../utils').processor();
12
131var ConnectionPool = exports.ConnectionPool = function(host, port, poolSize, bson, socketOptions) {
141 if(typeof host !== 'string') {
150 throw new Error("host must be specified [" + host + "]");
16 }
17
18 // Set up event emitter
191 EventEmitter.call(this);
20
21 // Keep all options for the socket in a specific collection allowing the user to specify the
22 // Wished upon socket connection parameters
231 this.socketOptions = typeof socketOptions === 'object' ? socketOptions : {};
241 this.socketOptions.host = host;
251 this.socketOptions.port = port;
261 this.socketOptions.domainSocket = false;
271 this.bson = bson;
28 // PoolSize is always + 1 for special reserved "measurment" socket (like ping, stats etc)
291 this.poolSize = poolSize;
301 this.minPoolSize = Math.floor(this.poolSize / 2) + 1;
31
32 // Check if the host is a socket
331 if(host.match(/^\//)) {
340 this.socketOptions.domainSocket = true;
351 } else if(typeof port === 'string') {
360 try {
370 port = parseInt(port, 10);
38 } catch(err) {
390 new Error("port must be specified or valid integer[" + port + "]");
40 }
411 } else if(typeof port !== 'number') {
420 throw new Error("port must be specified [" + port + "]");
43 }
44
45 // Set default settings for the socket options
461 utils.setIntegerParameter(this.socketOptions, 'timeout', 0);
47 // Delay before writing out the data to the server
481 utils.setBooleanParameter(this.socketOptions, 'noDelay', true);
49 // Delay before writing out the data to the server
501 utils.setIntegerParameter(this.socketOptions, 'keepAlive', 0);
51 // Set the encoding of the data read, default is binary == null
521 utils.setStringParameter(this.socketOptions, 'encoding', null);
53 // Allows you to set a throttling bufferSize if you need to stop overflows
541 utils.setIntegerParameter(this.socketOptions, 'bufferSize', 0);
55
56 // Internal structures
571 this.openConnections = [];
58 // Assign connection id's
591 this.connectionId = 0;
60
61 // Current index for selection of pool connection
621 this.currentConnectionIndex = 0;
63 // The pool state
641 this._poolState = 'disconnected';
65 // timeout control
661 this._timeout = false;
67 // Time to wait between connections for the pool
681 this._timeToWait = 10;
69}
70
711inherits(ConnectionPool, EventEmitter);
72
731ConnectionPool.prototype.setMaxBsonSize = function(maxBsonSize) {
740 if(maxBsonSize == null){
750 maxBsonSize = Connection.DEFAULT_MAX_BSON_SIZE;
76 }
77
780 for(var i = 0; i < this.openConnections.length; i++) {
790 this.openConnections[i].maxBsonSize = maxBsonSize;
800 this.openConnections[i].maxBsonSettings.maxBsonSize = maxBsonSize;
81 }
82}
83
841ConnectionPool.prototype.setMaxMessageSizeBytes = function(maxMessageSizeBytes) {
850 if(maxMessageSizeBytes == null){
860 maxMessageSizeBytes = Connection.DEFAULT_MAX_MESSAGE_SIZE;
87 }
88
890 for(var i = 0; i < this.openConnections.length; i++) {
900 this.openConnections[i].maxMessageSizeBytes = maxMessageSizeBytes;
910 this.openConnections[i].maxBsonSettings.maxMessageSizeBytes = maxMessageSizeBytes;
92 }
93}
94
95// Start a function
961var _connect = function(_self) {
97 // return new function() {
98 // Create a new connection instance
991 var connection = new Connection(_self.connectionId++, _self.socketOptions);
100 // Set logger on pool
1011 connection.logger = _self.logger;
102 // Connect handler
1031 connection.on("connect", function(err, connection) {
104 // Add connection to list of open connections
1050 _self.openConnections.push(connection);
106 // If the number of open connections is equal to the poolSize signal ready pool
1070 if(_self.openConnections.length === _self.poolSize && _self._poolState !== 'disconnected') {
108 // Set connected
1090 _self._poolState = 'connected';
110 // Emit pool ready
1110 _self.emit("poolReady");
1120 } else if(_self.openConnections.length < _self.poolSize) {
113 // Wait a little bit of time to let the close event happen if the server closes the connection
114 // so we don't leave hanging connections around
1150 if(typeof _self._timeToWait == 'number') {
1160 setTimeout(function() {
117 // If we are still connecting (no close events fired in between start another connection)
1180 if(_self._poolState == 'connecting') {
1190 _connect(_self);
120 }
121 }, _self._timeToWait);
122 } else {
1230 processor(function() {
124 // If we are still connecting (no close events fired in between start another connection)
1250 if(_self._poolState == 'connecting') {
1260 _connect(_self);
127 }
128 });
129 }
130 }
131 });
132
1331 var numberOfErrors = 0
134
135 // Error handler
1361 connection.on("error", function(err, connection, error_options) {
1370 numberOfErrors++;
138 // If we are already disconnected ignore the event
1390 if(_self._poolState != 'disconnected' && _self.listeners("error").length > 0) {
1400 _self.emit("error", err, connection, error_options);
141 }
142
143 // Close the connection
1440 connection.close();
145 // Set pool as disconnected
1460 _self._poolState = 'disconnected';
147 // Stop the pool
1480 _self.stop();
149 });
150
151 // Close handler
1521 connection.on("close", function() {
153 // If we are already disconnected ignore the event
1540 if(_self._poolState !== 'disconnected' && _self.listeners("close").length > 0) {
1550 _self.emit("close");
156 }
157
158 // Set disconnected
1590 _self._poolState = 'disconnected';
160 // Stop
1610 _self.stop();
162 });
163
164 // Timeout handler
1651 connection.on("timeout", function(err, connection) {
166 // If we are already disconnected ignore the event
1670 if(_self._poolState !== 'disconnected' && _self.listeners("timeout").length > 0) {
1680 _self.emit("timeout", err);
169 }
170
171 // Close the connection
1720 connection.close();
173 // Set disconnected
1740 _self._poolState = 'disconnected';
1750 _self.stop();
176 });
177
178 // Parse error, needs a complete shutdown of the pool
1791 connection.on("parseError", function() {
180 // If we are already disconnected ignore the event
1810 if(_self._poolState !== 'disconnected' && _self.listeners("parseError").length > 0) {
1820 _self.emit("parseError", new Error("parseError occured"));
183 }
184
185 // Set disconnected
1860 _self._poolState = 'disconnected';
1870 _self.stop();
188 });
189
1901 connection.on("message", function(message) {
1910 _self.emit("message", message);
192 });
193
194 // Start connection in the next tick
1951 connection.start();
196 // }();
197}
198
199
200// Start method, will throw error if no listeners are available
201// Pass in an instance of the listener that contains the api for
202// finding callbacks for a given message etc.
2031ConnectionPool.prototype.start = function() {
2041 var markerDate = new Date().getTime();
2051 var self = this;
206
2071 if(this.listeners("poolReady").length == 0) {
2080 throw "pool must have at least one listener ready that responds to the [poolReady] event";
209 }
210
211 // Set pool state to connecting
2121 this._poolState = 'connecting';
2131 this._timeout = false;
214
2151 _connect(self);
216}
217
218// Restart a connection pool (on a close the pool might be in a wrong state)
2191ConnectionPool.prototype.restart = function() {
220 // Close all connections
2210 this.stop(false);
222 // Now restart the pool
2230 this.start();
224}
225
226// Stop the connections in the pool
2271ConnectionPool.prototype.stop = function(removeListeners) {
2280 removeListeners = removeListeners == null ? true : removeListeners;
229 // Set disconnected
2300 this._poolState = 'disconnected';
231
232 // Clear all listeners if specified
2330 if(removeListeners) {
2340 this.removeAllEventListeners();
235 }
236
237 // Close all connections
2380 for(var i = 0; i < this.openConnections.length; i++) {
2390 this.openConnections[i].close();
240 }
241
242 // Clean up
2430 this.openConnections = [];
244}
245
246// Check the status of the connection
2471ConnectionPool.prototype.isConnected = function() {
248 // return this._poolState === 'connected';
2490 return this.openConnections.length > 0 && this.openConnections[0].isConnected();
250}
251
252// Checkout a connection from the pool for usage, or grab a specific pool instance
2531ConnectionPool.prototype.checkoutConnection = function(id) {
2540 var index = (this.currentConnectionIndex++ % (this.openConnections.length));
2550 var connection = this.openConnections[index];
2560 return connection;
257}
258
2591ConnectionPool.prototype.getAllConnections = function() {
2600 return this.openConnections;
261}
262
263// Remove all non-needed event listeners
2641ConnectionPool.prototype.removeAllEventListeners = function() {
2650 this.removeAllListeners("close");
2660 this.removeAllListeners("error");
2670 this.removeAllListeners("timeout");
2680 this.removeAllListeners("connect");
2690 this.removeAllListeners("end");
2700 this.removeAllListeners("parseError");
2710 this.removeAllListeners("message");
2720 this.removeAllListeners("poolReady");
273}
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_utils.js

60%
15
9
6
LineHitsSource
11exports.setIntegerParameter = function(object, field, defaultValue) {
23 if(object[field] == null) {
33 object[field] = defaultValue;
40 } else if(typeof object[field] !== "number" && object[field] !== parseInt(object[field], 10)) {
50 throw "object field [" + field + "] must be a numeric integer value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]";
6 }
7}
8
91exports.setBooleanParameter = function(object, field, defaultValue) {
101 if(object[field] == null) {
111 object[field] = defaultValue;
120 } else if(typeof object[field] !== "boolean") {
130 throw "object field [" + field + "] must be a boolean value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]";
14 }
15}
16
171exports.setStringParameter = function(object, field, defaultValue) {
181 if(object[field] == null) {
191 object[field] = defaultValue;
200 } else if(typeof object[field] !== "string") {
210 throw "object field [" + field + "] must be a string value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]";
22 }
23}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/mongos.js

9%
203
20
183
LineHitsSource
11var ReadPreference = require('./read_preference').ReadPreference
2 , Base = require('./base').Base
3 , Server = require('./server').Server
4 , format = require('util').format
5 , timers = require('timers')
6 , utils = require('../utils')
7 , inherits = require('util').inherits;
8
9// Set processor, setImmediate if 0.10 otherwise nextTick
101var processor = require('../utils').processor();
11
12/**
13 * Mongos constructor provides a connection to a mongos proxy including failover to additional servers
14 *
15 * Options
16 * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number))
17 * - **ha** {Boolean, default:true}, turn on high availability, attempts to reconnect to down proxies
18 * - **haInterval** {Number, default:2000}, time between each replicaset status check.
19 *
20 * @class Represents a Mongos connection with failover to backup proxies
21 * @param {Array} list of mongos server objects
22 * @param {Object} [options] additional options for the mongos connection
23 */
241var Mongos = function Mongos(servers, options) {
25 // Set up basic
260 if(!(this instanceof Mongos))
270 return new Mongos(servers, options);
28
29 // Set up event emitter
300 Base.call(this);
31
32 // Throw error on wrong setup
330 if(servers == null || !Array.isArray(servers) || servers.length == 0)
340 throw new Error("At least one mongos proxy must be in the array");
35
36 // Ensure we have at least an empty options object
370 this.options = options == null ? {} : options;
38 // Set default connection pool options
390 this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {};
40 // Enabled ha
410 this.haEnabled = this.options['ha'] == null ? true : this.options['ha'];
420 this._haInProgress = false;
43 // How often are we checking for new servers in the replicaset
440 this.mongosStatusCheckInterval = this.options['haInterval'] == null ? 1000 : this.options['haInterval'];
45 // Save all the server connections
460 this.servers = servers;
47 // Servers we need to attempt reconnect with
480 this.downServers = {};
49 // Servers that are up
500 this.upServers = {};
51 // Up servers by ping time
520 this.upServersByUpTime = {};
53 // Emit open setup
540 this.emitOpen = this.options.emitOpen || true;
55 // Just contains the current lowest ping time and server
560 this.lowestPingTimeServer = null;
570 this.lowestPingTime = 0;
58 // Connection timeout
590 this._connectTimeoutMS = this.socketOptions.connectTimeoutMS
60 ? this.socketOptions.connectTimeoutMS
61 : 1000;
62
63 // Add options to servers
640 for(var i = 0; i < this.servers.length; i++) {
650 var server = this.servers[i];
660 server._callBackStore = this._callBackStore;
670 server.auto_reconnect = false;
68 // Default empty socket options object
690 var socketOptions = {host: server.host, port: server.port};
70 // If a socket option object exists clone it
710 if(this.socketOptions != null) {
720 var keys = Object.keys(this.socketOptions);
730 for(var k = 0; k < keys.length;k++) socketOptions[keys[i]] = this.socketOptions[keys[i]];
74 }
75
76 // Set socket options
770 server.socketOptions = socketOptions;
78 }
79
80 // Allow setting the socketTimeoutMS on all connections
81 // to work around issues such as secondaries blocking due to compaction
820 utils.setSocketTimeoutProperty(this, this.socketOptions);
83}
84
85/**
86 * @ignore
87 */
881inherits(Mongos, Base);
89
90/**
91 * @ignore
92 */
931Mongos.prototype.isMongos = function() {
940 return true;
95}
96
97/**
98 * @ignore
99 */
1001Mongos.prototype.connect = function(db, options, callback) {
1010 if('function' === typeof options) callback = options, options = {};
1020 if(options == null) options = {};
1030 if(!('function' === typeof callback)) callback = null;
1040 var self = this;
105
106 // Keep reference to parent
1070 this.db = db;
108 // Set server state to connecting
1090 this._serverState = 'connecting';
110 // Number of total servers that need to initialized (known servers)
1110 this._numberOfServersLeftToInitialize = this.servers.length;
112 // Connect handler
1130 var connectHandler = function(_server) {
1140 return function(err, result) {
1150 self._numberOfServersLeftToInitialize = self._numberOfServersLeftToInitialize - 1;
116
117 // Add the server to the list of servers that are up
1180 if(!err) {
1190 self.upServers[format("%s:%s", _server.host, _server.port)] = _server;
120 }
121
122 // We are done connecting
1230 if(self._numberOfServersLeftToInitialize == 0) {
124 // Start ha function if it exists
1250 if(self.haEnabled) {
126 // Setup the ha process
1270 if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId);
1280 self._replicasetTimeoutId = setInterval(self.mongosCheckFunction, self.mongosStatusCheckInterval);
129 }
130
131 // Set the mongos to connected
1320 self._serverState = "connected";
133
134 // Emit the open event
1350 if(self.emitOpen)
1360 self._emitAcrossAllDbInstances(self, null, "open", null, null, null);
137
1380 self._emitAcrossAllDbInstances(self, null, "fullsetup", null, null, null);
139 // Callback
1400 callback(null, self.db);
141 }
142 }
143 };
144
145 // Error handler
1460 var errorOrCloseHandler = function(_server) {
1470 return function(err, result) {
148 // Emit left event, signaling mongos left the ha
1490 self.emit('left', 'mongos', _server);
150 // Execute all the callbacks with errors
1510 self.__executeAllCallbacksWithError(err);
152 // Check if we have the server
1530 var found = false;
154
155 // Get the server name
1560 var server_name = format("%s:%s", _server.host, _server.port);
157 // Add the downed server
1580 self.downServers[server_name] = _server;
159 // Remove the current server from the list
1600 delete self.upServers[server_name];
161
162 // Emit close across all the attached db instances
1630 if(Object.keys(self.upServers).length == 0) {
1640 self._emitAcrossAllDbInstances(self, null, "close", new Error("mongos disconnected, no valid proxies contactable over tcp"), null, null);
165 }
166 }
167 }
168
169 // Mongo function
1700 this.mongosCheckFunction = function() {
171 // Set as not waiting for check event
1720 self._haInProgress = true;
173
174 // Servers down
1750 var numberOfServersLeft = Object.keys(self.downServers).length;
176
177 // Check downed servers
1780 if(numberOfServersLeft > 0) {
1790 for(var name in self.downServers) {
180 // Pop a downed server
1810 var downServer = self.downServers[name];
182 // Set up the connection options for a Mongos
1830 var options = {
184 auto_reconnect: false,
185 returnIsMasterResults: true,
186 slaveOk: true,
187 poolSize: downServer.poolSize,
188 socketOptions: {
189 connectTimeoutMS: self._connectTimeoutMS,
190 socketTimeoutMS: self._socketTimeoutMS
191 }
192 }
193
194 // Create a new server object
1950 var newServer = new Server(downServer.host, downServer.port, options);
196 // Setup the connection function
1970 var connectFunction = function(_db, _server, _options, _callback) {
1980 return function() {
199 // Attempt to connect
2000 _server.connect(_db, _options, function(err, result) {
2010 numberOfServersLeft = numberOfServersLeft - 1;
202
2030 if(err) {
2040 return _callback(err, _server);
205 } else {
206 // Set the new server settings
2070 _server._callBackStore = self._callBackStore;
208
209 // Add server event handlers
2100 _server.on("close", errorOrCloseHandler(_server));
2110 _server.on("timeout", errorOrCloseHandler(_server));
2120 _server.on("error", errorOrCloseHandler(_server));
213
214 // Get a read connection
2150 var _connection = _server.checkoutReader();
216 // Get the start time
2170 var startTime = new Date().getTime();
218
219 // Execute ping command to mark each server with the expected times
2200 self.db.command({ping:1}
221 , {failFast:true, connection:_connection}, function(err, result) {
222 // Get the start time
2230 var endTime = new Date().getTime();
224 // Mark the server with the ping time
2250 _server.runtimeStats['pingMs'] = endTime - startTime;
226 // Execute any waiting reads
2270 self._commandsStore.execute_writes();
2280 self._commandsStore.execute_queries();
229 // Callback
2300 return _callback(null, _server);
231 });
232 }
233 });
234 }
235 }
236
237 // Attempt to connect to the database
2380 connectFunction(self.db, newServer, options, function(err, _server) {
239 // If we have an error
2400 if(err) {
2410 self.downServers[format("%s:%s", _server.host, _server.port)] = _server;
242 }
243
244 // Connection function
2450 var connectionFunction = function(_auth, _connection, _callback) {
2460 var pending = _auth.length();
247
2480 for(var j = 0; j < pending; j++) {
249 // Get the auth object
2500 var _auth = _auth.get(j);
251 // Unpack the parameter
2520 var username = _auth.username;
2530 var password = _auth.password;
2540 var options = {
255 authMechanism: _auth.authMechanism
256 , authSource: _auth.authdb
257 , connection: _connection
258 };
259
260 // If we have changed the service name
2610 if(_auth.gssapiServiceName)
2620 options.gssapiServiceName = _auth.gssapiServiceName;
263
264 // Hold any error
2650 var _error = null;
266 // Authenticate against the credentials
2670 self.db.authenticate(username, password, options, function(err, result) {
2680 _error = err != null ? err : _error;
269 // Adjust the pending authentication
2700 pending = pending - 1;
271 // Finished up
2720 if(pending == 0) _callback(_error ? _error : null, _error ? false : true);
273 });
274 }
275 }
276
277 // Run auths against the connections
2780 if(self.auth.length() > 0) {
2790 var connections = _server.allRawConnections();
2800 var pendingAuthConn = connections.length;
281
282 // No connections we are done
2830 if(connections.length == 0) {
284 // Set ha done
2850 if(numberOfServersLeft == 0) {
2860 self._haInProgress = false;
287 }
288 }
289
290 // Final error object
2910 var finalError = null;
292 // Go over all the connections
2930 for(var j = 0; j < connections.length; j++) {
294
295 // Execute against all the connections
2960 connectionFunction(self.auth, connections[j], function(err, result) {
297 // Pending authentication
2980 pendingAuthConn = pendingAuthConn - 1 ;
299
300 // Save error if any
3010 finalError = err ? err : finalError;
302
303 // If we are done let's finish up
3040 if(pendingAuthConn == 0) {
305 // Set ha done
3060 if(numberOfServersLeft == 0) {
3070 self._haInProgress = false;
308 }
309
3100 if(!err) {
3110 add_server(self, _server);
312 }
313
314 // Execute any waiting reads
3150 self._commandsStore.execute_writes();
3160 self._commandsStore.execute_queries();
317 }
318 });
319 }
320 } else {
3210 if(!err) {
3220 add_server(self, _server);
323 }
324
325 // Set ha done
3260 if(numberOfServersLeft == 0) {
3270 self._haInProgress = false;
328 // Execute any waiting reads
3290 self._commandsStore.execute_writes();
3300 self._commandsStore.execute_queries();
331 }
332 }
333 })();
334 }
335 } else {
3360 self._haInProgress = false;
337 }
338 }
339
340 // Connect all the server instances
3410 for(var i = 0; i < this.servers.length; i++) {
342 // Get the connection
3430 var server = this.servers[i];
3440 server.mongosInstance = this;
345 // Add server event handlers
3460 server.on("close", errorOrCloseHandler(server));
3470 server.on("timeout", errorOrCloseHandler(server));
3480 server.on("error", errorOrCloseHandler(server));
349
350 // Configuration
3510 var options = {
352 slaveOk: true,
353 poolSize: server.poolSize,
354 socketOptions: { connectTimeoutMS: self._connectTimeoutMS },
355 returnIsMasterResults: true
356 }
357
358 // Connect the instance
3590 server.connect(self.db, options, connectHandler(server));
360 }
361}
362
363/**
364 * @ignore
365 * Add a server to the list of up servers and sort them by ping time
366 */
3671var add_server = function(self, _server) {
368 // Emit a new server joined
3690 self.emit('joined', "mongos", null, _server);
370 // Get the server url
3710 var server_key = format("%s:%s", _server.host, _server.port);
372 // Push to list of valid server
3730 self.upServers[server_key] = _server;
374 // Remove the server from the list of downed servers
3750 delete self.downServers[server_key];
376
377 // Sort the keys by ping time
3780 var keys = Object.keys(self.upServers);
3790 var _upServersSorted = {};
3800 var _upServers = []
381
382 // Get all the servers
3830 for(var name in self.upServers) {
3840 _upServers.push(self.upServers[name]);
385 }
386
387 // Sort all the server
3880 _upServers.sort(function(a, b) {
3890 return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs'];
390 });
391
392 // Rebuild the upServer
3930 for(var i = 0; i < _upServers.length; i++) {
3940 _upServersSorted[format("%s:%s", _upServers[i].host, _upServers[i].port)] = _upServers[i];
395 }
396
397 // Set the up servers
3980 self.upServers = _upServersSorted;
399}
400
401/**
402 * @ignore
403 * Just return the currently picked active connection
404 */
4051Mongos.prototype.allServerInstances = function() {
4060 return this.servers;
407}
408
409/**
410 * Always ourselves
411 * @ignore
412 */
4131Mongos.prototype.setReadPreference = function() {}
414
415/**
416 * @ignore
417 */
4181Mongos.prototype.allRawConnections = function() {
419 // Neeed to build a complete list of all raw connections, start with master server
4200 var allConnections = [];
421 // Get all connected connections
4220 for(var name in this.upServers) {
4230 allConnections = allConnections.concat(this.upServers[name].allRawConnections());
424 }
425 // Return all the conections
4260 return allConnections;
427}
428
429/**
430 * @ignore
431 */
4321Mongos.prototype.isConnected = function() {
4330 return Object.keys(this.upServers).length > 0;
434}
435
436/**
437 * @ignore
438 */
4391Mongos.prototype.isAutoReconnect = function() {
4400 return true;
441}
442
443/**
444 * @ignore
445 */
4461Mongos.prototype.canWrite = Mongos.prototype.isConnected;
447
448/**
449 * @ignore
450 */
4511Mongos.prototype.canRead = Mongos.prototype.isConnected;
452
453/**
454 * @ignore
455 */
4561Mongos.prototype.isDestroyed = function() {
4570 return this._serverState == 'destroyed';
458}
459
460/**
461 * @ignore
462 */
4631Mongos.prototype.checkoutWriter = function() {
464 // Checkout a writer
4650 var keys = Object.keys(this.upServers);
466 // console.dir("============================ checkoutWriter :: " + keys.length)
4670 if(keys.length == 0) return null;
468 // console.log("=============== checkoutWriter :: " + this.upServers[keys[0]].checkoutWriter().socketOptions.port)
4690 return this.upServers[keys[0]].checkoutWriter();
470}
471
472/**
473 * @ignore
474 */
4751Mongos.prototype.checkoutReader = function(read) {
476 // console.log("=============== checkoutReader :: read :: " + read);
477 // If read is set to null default to primary
4780 read = read || 'primary'
479 // If we have a read preference object unpack it
4800 if(read != null && typeof read == 'object' && read['_type'] == 'ReadPreference') {
481 // Validate if the object is using a valid mode
4820 if(!read.isValid()) throw new Error("Illegal readPreference mode specified, " + read.mode);
4830 } else if(!ReadPreference.isValid(read)) {
4840 throw new Error("Illegal readPreference mode specified, " + read);
485 }
486
487 // Checkout a writer
4880 var keys = Object.keys(this.upServers);
4890 if(keys.length == 0) return null;
490 // console.log("=============== checkoutReader :: " + this.upServers[keys[0]].checkoutWriter().socketOptions.port)
491 // console.dir(this._commandsStore.commands)
4920 return this.upServers[keys[0]].checkoutWriter();
493}
494
495/**
496 * @ignore
497 */
4981Mongos.prototype.close = function(callback) {
4990 var self = this;
500 // Set server status as disconnected
5010 this._serverState = 'destroyed';
502 // Number of connections to close
5030 var numberOfConnectionsToClose = self.servers.length;
504 // If we have a ha process running kill it
5050 if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId);
5060 self._replicasetTimeoutId = null;
507
508 // Emit close event
5090 processor(function() {
5100 self._emitAcrossAllDbInstances(self, null, "close", null, null, true)
511 });
512
513 // Flush out any remaining call handlers
5140 self._flushAllCallHandlers(utils.toError("Connection Closed By Application"));
515
516 // Close all the up servers
5170 for(var name in this.upServers) {
5180 this.upServers[name].close(function(err, result) {
5190 numberOfConnectionsToClose = numberOfConnectionsToClose - 1;
520
521 // Callback if we have one defined
5220 if(numberOfConnectionsToClose == 0 && typeof callback == 'function') {
5230 callback(null);
524 }
525 });
526 }
527}
528
529/**
530 * @ignore
531 * Return the used state
532 */
5331Mongos.prototype._isUsed = function() {
5340 return this._used;
535}
536
5371exports.Mongos = Mongos;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/read_preference.js

45%
22
10
12
LineHitsSource
1/**
2 * A class representation of the Read Preference.
3 *
4 * Read Preferences
5 * - **ReadPreference.PRIMARY**, Read from primary only. All operations produce an error (throw an exception where applicable) if primary is unavailable. Cannot be combined with tags (This is the default.).
6 * - **ReadPreference.PRIMARY_PREFERRED**, Read from primary if available, otherwise a secondary.
7 * - **ReadPreference.SECONDARY**, Read from secondary if available, otherwise error.
8 * - **ReadPreference.SECONDARY_PREFERRED**, Read from a secondary if available, otherwise read from the primary.
9 * - **ReadPreference.NEAREST**, All modes read from among the nearest candidates, but unlike other modes, NEAREST will include both the primary and all secondaries in the random selection.
10 *
11 * @class Represents a Read Preference.
12 * @param {String} the read preference type
13 * @param {Object} tags
14 * @return {ReadPreference}
15 */
161var ReadPreference = function(mode, tags) {
170 if(!(this instanceof ReadPreference))
180 return new ReadPreference(mode, tags);
190 this._type = 'ReadPreference';
200 this.mode = mode;
210 this.tags = tags;
22}
23
24/**
25 * @ignore
26 */
271ReadPreference.isValid = function(_mode) {
280 return (_mode == ReadPreference.PRIMARY || _mode == ReadPreference.PRIMARY_PREFERRED
29 || _mode == ReadPreference.SECONDARY || _mode == ReadPreference.SECONDARY_PREFERRED
30 || _mode == ReadPreference.NEAREST
31 || _mode == true || _mode == false);
32}
33
34/**
35 * @ignore
36 */
371ReadPreference.prototype.isValid = function(mode) {
380 var _mode = typeof mode == 'string' ? mode : this.mode;
390 return ReadPreference.isValid(_mode);
40}
41
42/**
43 * @ignore
44 */
451ReadPreference.prototype.toObject = function() {
460 var object = {mode:this.mode};
47
480 if(this.tags != null) {
490 object['tags'] = this.tags;
50 }
51
520 return object;
53}
54
55/**
56 * @ignore
57 */
581ReadPreference.PRIMARY = 'primary';
591ReadPreference.PRIMARY_PREFERRED = 'primaryPreferred';
601ReadPreference.SECONDARY = 'secondary';
611ReadPreference.SECONDARY_PREFERRED = 'secondaryPreferred';
621ReadPreference.NEAREST = 'nearest'
63
64/**
65 * @ignore
66 */
671exports.ReadPreference = ReadPreference;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js

6%
196
13
183
LineHitsSource
11var DbCommand = require('../../commands/db_command').DbCommand
2 , format = require('util').format;
3
41var HighAvailabilityProcess = function(replset, options) {
50 this.replset = replset;
60 this.options = options;
70 this.server = null;
80 this.state = HighAvailabilityProcess.INIT;
90 this.selectedIndex = 0;
10}
11
121HighAvailabilityProcess.INIT = 'init';
131HighAvailabilityProcess.RUNNING = 'running';
141HighAvailabilityProcess.STOPPED = 'stopped';
15
161HighAvailabilityProcess.prototype.start = function() {
170 var self = this;
180 if(this.replset._state
19 && Object.keys(this.replset._state.addresses).length == 0) {
200 if(this.server) this.server.close();
210 this.state = HighAvailabilityProcess.STOPPED;
220 return;
23 }
24
250 if(this.server) this.server.close();
26 // Start the running
270 this._haProcessInProcess = false;
280 this.state = HighAvailabilityProcess.RUNNING;
29
30 // Get all possible reader servers
310 var candidate_servers = this.replset._state.getAllReadServers();
320 if(candidate_servers.length == 0) {
330 return;
34 }
35
36 // Select a candidate server for the connection
370 var server = candidate_servers[this.selectedIndex % candidate_servers.length];
380 this.selectedIndex = this.selectedIndex + 1;
39
40 // Unpack connection options
410 var connectTimeoutMS = self.options.connectTimeoutMS || 10000;
420 var socketTimeoutMS = self.options.socketTimeoutMS || 30000;
43
44 // Just ensure we don't have a full cycle dependency
450 var Db = require('../../db').Db
460 var Server = require('../server').Server;
47
48 // Set up a new server instance
490 var newServer = new Server(server.host, server.port, {
50 auto_reconnect: false
51 , returnIsMasterResults: true
52 , poolSize: 1
53 , socketOptions: {
54 connectTimeoutMS: connectTimeoutMS,
55 socketTimeoutMS: socketTimeoutMS,
56 keepAlive: 100
57 }
58 , ssl: this.options.ssl
59 , sslValidate: this.options.sslValidate
60 , sslCA: this.options.sslCA
61 , sslCert: this.options.sslCert
62 , sslKey: this.options.sslKey
63 , sslPass: this.options.sslPass
64 });
65
66 // Create new dummy db for app
670 self.db = new Db('local', newServer, {w:1});
68
69 // Set up the event listeners
700 newServer.once("error", _handle(this, newServer));
710 newServer.once("close", _handle(this, newServer));
720 newServer.once("timeout", _handle(this, newServer));
730 newServer.name = format("%s:%s", server.host, server.port);
74
75 // Let's attempt a connection over here
760 newServer.connect(self.db, function(err, result, _server) {
770 if(self.state == HighAvailabilityProcess.STOPPED) {
780 _server.close();
79 }
80
810 if(err) {
82 // Close the server
830 _server.close();
84 // Check if we can even do HA (is there anything running)
850 if(Object.keys(self.replset._state.addresses).length == 0) {
860 return;
87 }
88
89 // Let's boot the ha timeout settings
900 setTimeout(function() {
910 self.start();
92 }, self.options.haInterval);
93 } else {
940 self.server = _server;
95 // Let's boot the ha timeout settings
960 setTimeout(_timeoutHandle(self), self.options.haInterval);
97 }
98 });
99}
100
1011HighAvailabilityProcess.prototype.stop = function() {
1020 this.state = HighAvailabilityProcess.STOPPED;
1030 if(this.server) this.server.close();
104}
105
1061var _timeoutHandle = function(self) {
1070 return function() {
1080 if(self.state == HighAvailabilityProcess.STOPPED) {
109 // Stop all server instances
1100 for(var name in self.replset._state.addresses) {
1110 self.replset._state.addresses[name].close();
1120 delete self.replset._state.addresses[name];
113 }
114
115 // Finished pinging
1160 return;
117 }
118
119 // If the server is connected
1200 if(self.server.isConnected() && !self._haProcessInProcess) {
121 // Start HA process
1220 self._haProcessInProcess = true;
123 // Execute is master command
1240 self.db._executeQueryCommand(DbCommand.createIsMasterCommand(self.db),
125 {failFast:true, connection: self.server.checkoutReader()}
126 , function(err, res) {
1270 if(err) {
1280 self.server.close();
1290 return setTimeout(_timeoutHandle(self), self.options.haInterval);
130 }
131
132 // Master document
1330 var master = res.documents[0];
1340 var hosts = master.hosts || [];
1350 var reconnect_servers = [];
1360 var state = self.replset._state;
137
138 // We are in recovery mode, let's remove the current server
1390 if(!master.ismaster
140 && !master.secondary
141 && state.addresses[master.me]) {
1420 self.server.close();
1430 state.addresses[master.me].close();
1440 delete state.secondaries[master.me];
1450 return setTimeout(_timeoutHandle(self), self.options.haInterval);
146 }
147
148 // For all the hosts let's check that we have connections
1490 for(var i = 0; i < hosts.length; i++) {
1500 var host = hosts[i];
151 // Check if we need to reconnect to a server
1520 if(state.addresses[host] == null) {
1530 reconnect_servers.push(host);
1540 } else if(state.addresses[host] && !state.addresses[host].isConnected()) {
1550 state.addresses[host].close();
1560 delete state.secondaries[host];
1570 reconnect_servers.push(host);
158 }
159
1600 if((master.primary && state.master == null)
161 || (master.primary && state.master.name != master.primary)) {
162
163 // Locate the primary and set it
1640 if(state.addresses[master.primary]) {
1650 if(state.master) state.master.close();
1660 delete state.secondaries[master.primary];
1670 state.master = state.addresses[master.primary];
168 }
169
170 // Set up the changes
1710 if(state.master != null && state.master.isMasterDoc != null) {
1720 state.master.isMasterDoc.ismaster = true;
1730 state.master.isMasterDoc.secondary = false;
1740 } else if(state.master != null) {
1750 state.master.isMasterDoc = master;
1760 state.master.isMasterDoc.ismaster = true;
1770 state.master.isMasterDoc.secondary = false;
178 }
179
180 // Execute any waiting commands (queries or writes)
1810 self.replset._commandsStore.execute_queries();
1820 self.replset._commandsStore.execute_writes();
183 }
184 }
185
186 // Let's reconnect to any server needed
1870 if(reconnect_servers.length > 0) {
1880 _reconnect_servers(self, reconnect_servers);
189 } else {
1900 self._haProcessInProcess = false
1910 return setTimeout(_timeoutHandle(self), self.options.haInterval);
192 }
193 });
1940 } else if(!self.server.isConnected()) {
1950 setTimeout(function() {
1960 return self.start();
197 }, self.options.haInterval);
198 } else {
1990 setTimeout(_timeoutHandle(self), self.options.haInterval);
200 }
201 }
202}
203
2041var _reconnect_servers = function(self, reconnect_servers) {
2050 if(reconnect_servers.length == 0) {
2060 self._haProcessInProcess = false
2070 return setTimeout(_timeoutHandle(self), self.options.haInterval);
208 }
209
210 // Unpack connection options
2110 var connectTimeoutMS = self.options.connectTimeoutMS || 10000;
2120 var socketTimeoutMS = self.options.socketTimeoutMS || 0;
213
214 // Server class
2150 var Db = require('../../db').Db
2160 var Server = require('../server').Server;
217 // Get the host
2180 var host = reconnect_servers.shift();
219 // Split it up
2200 var _host = host.split(":")[0];
2210 var _port = parseInt(host.split(":")[1], 10);
222
223 // Set up a new server instance
2240 var newServer = new Server(_host, _port, {
225 auto_reconnect: false
226 , returnIsMasterResults: true
227 , poolSize: self.options.poolSize
228 , socketOptions: {
229 connectTimeoutMS: connectTimeoutMS,
230 socketTimeoutMS: socketTimeoutMS
231 }
232 , ssl: self.options.ssl
233 , sslValidate: self.options.sslValidate
234 , sslCA: self.options.sslCA
235 , sslCert: self.options.sslCert
236 , sslKey: self.options.sslKey
237 , sslPass: self.options.sslPass
238 });
239
240 // Create new dummy db for app
2410 var db = new Db('local', newServer, {w:1});
2420 var state = self.replset._state;
243
244 // Set up the event listeners
2450 newServer.once("error", _repl_set_handler("error", self.replset, newServer));
2460 newServer.once("close", _repl_set_handler("close", self.replset, newServer));
2470 newServer.once("timeout", _repl_set_handler("timeout", self.replset, newServer));
248
249 // Set shared state
2500 newServer.name = host;
2510 newServer._callBackStore = self.replset._callBackStore;
2520 newServer.replicasetInstance = self.replset;
2530 newServer.enableRecordQueryStats(self.replset.recordQueryStats);
254
255 // Let's attempt a connection over here
2560 newServer.connect(db, function(err, result, _server) {
2570 if(self.state == HighAvailabilityProcess.STOPPED) {
2580 _server.close();
259 }
260
261 // If we connected let's check what kind of server we have
2620 if(!err) {
2630 _apply_auths(self, db, _server, function(err, result) {
2640 if(err) {
2650 _server.close();
266 // Process the next server
2670 return setTimeout(function() {
2680 _reconnect_servers(self, reconnect_servers);
269 }, self.options.haInterval);
270 }
2710 var doc = _server.isMasterDoc;
272 // Fire error on any unknown callbacks for this server
2730 self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err);
274
2750 if(doc.ismaster) {
276 // Emit primary added
2770 self.replset.emit('joined', "primary", doc, _server);
278
279 // If it was a secondary remove it
2800 if(state.secondaries[doc.me]) {
2810 delete state.secondaries[doc.me];
282 }
283
284 // Override any server in list of addresses
2850 state.addresses[doc.me] = _server;
286 // Set server as master
2870 state.master = _server;
288 // Execute any waiting writes
2890 self.replset._commandsStore.execute_writes();
2900 } else if(doc.secondary) {
291 // Emit secondary added
2920 self.replset.emit('joined', "secondary", doc, _server);
293 // Add the secondary to the state
2940 state.secondaries[doc.me] = _server;
295 // Override any server in list of addresses
2960 state.addresses[doc.me] = _server;
297 // Execute any waiting reads
2980 self.replset._commandsStore.execute_queries();
299 } else {
3000 _server.close();
301 }
302
303 // Set any tags on the instance server
3040 _server.name = doc.me;
3050 _server.tags = doc.tags;
306 // Process the next server
3070 setTimeout(function() {
3080 _reconnect_servers(self, reconnect_servers);
309 }, self.options.haInterval);
310 });
311 } else {
3120 _server.close();
3130 self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err);
314
3150 setTimeout(function() {
3160 _reconnect_servers(self, reconnect_servers);
317 }, self.options.haInterval);
318 }
319 });
320}
321
3221var _apply_auths = function(self, _db, _server, _callback) {
3230 if(self.replset.auth.length() == 0) return _callback(null);
324 // Apply any authentication needed
3250 if(self.replset.auth.length() > 0) {
3260 var pending = self.replset.auth.length();
3270 var connections = _server.allRawConnections();
3280 var pendingAuthConn = connections.length;
329
330 // Connection function
3310 var connectionFunction = function(_auth, _connection, __callback) {
3320 var pending = _auth.length();
333
3340 for(var j = 0; j < pending; j++) {
335 // Get the auth object
3360 var _auth = _auth.get(j);
337 // Unpack the parameter
3380 var username = _auth.username;
3390 var password = _auth.password;
3400 var options = {
341 authMechanism: _auth.authMechanism
342 , authSource: _auth.authdb
343 , connection: _connection
344 };
345
346 // If we have changed the service name
3470 if(_auth.gssapiServiceName)
3480 options.gssapiServiceName = _auth.gssapiServiceName;
349
350 // Hold any error
3510 var _error = null;
352
353 // Authenticate against the credentials
3540 _db.authenticate(username, password, options, function(err, result) {
3550 _error = err != null ? err : _error;
356 // Adjust the pending authentication
3570 pending = pending - 1;
358 // Finished up
3590 if(pending == 0) __callback(_error ? _error : null, _error ? false : true);
360 });
361 }
362 }
363
364 // Final error object
3650 var finalError = null;
366 // Iterate over all the connections
3670 for(var i = 0; i < connections.length; i++) {
3680 connectionFunction(self.replset.auth, connections[i], function(err, result) {
369 // Pending authentication
3700 pendingAuthConn = pendingAuthConn - 1 ;
371
372 // Save error if any
3730 finalError = err ? err : finalError;
374
375 // If we are done let's finish up
3760 if(pendingAuthConn == 0) {
3770 _callback(null);
378 }
379 });
380 }
381 }
382}
383
3841var _handle = function(self, server) {
3850 return function(err) {
3860 server.close();
387 }
388}
389
3901var _repl_set_handler = function(event, self, server) {
3910 var ReplSet = require('./repl_set').ReplSet;
392
3930 return function(err, doc) {
3940 server.close();
395
396 // The event happened to a primary
397 // Remove it from play
3980 if(self._state.isPrimary(server)) {
3990 self._state.master == null;
4000 self._serverState = ReplSet.REPLSET_READ_ONLY;
4010 } else if(self._state.isSecondary(server)) {
4020 delete self._state.secondaries[server.name];
403 }
404
405 // Unpack variables
4060 var host = server.socketOptions.host;
4070 var port = server.socketOptions.port;
408
409 // Fire error on any unknown callbacks
4100 self.__executeAllServerSpecificErrorCallbacks(host, port, err);
411 }
412}
413
4141exports.HighAvailabilityProcess = HighAvailabilityProcess;
415

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js

7%
66
5
61
LineHitsSource
11var PingStrategy = require('./strategies/ping_strategy').PingStrategy
2 , StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy
3 , ReadPreference = require('../read_preference').ReadPreference;
4
51var Options = function(options) {
60 options = options || {};
70 this._options = options;
80 this.ha = options.ha || true;
90 this.haInterval = options.haInterval || 2000;
100 this.reconnectWait = options.reconnectWait || 1000;
110 this.retries = options.retries || 30;
120 this.rs_name = options.rs_name;
130 this.socketOptions = options.socketOptions || {};
140 this.readPreference = options.readPreference;
150 this.readSecondary = options.read_secondary;
160 this.poolSize = options.poolSize == null ? 5 : options.poolSize;
170 this.strategy = options.strategy || 'ping';
180 this.secondaryAcceptableLatencyMS = options.secondaryAcceptableLatencyMS || 15;
190 this.connectArbiter = options.connectArbiter || false;
200 this.connectWithNoPrimary = options.connectWithNoPrimary || false;
210 this.logger = options.logger;
220 this.ssl = options.ssl || false;
230 this.sslValidate = options.sslValidate || false;
240 this.sslCA = options.sslCA;
250 this.sslCert = options.sslCert;
260 this.sslKey = options.sslKey;
270 this.sslPass = options.sslPass;
280 this.emitOpen = options.emitOpen || true;
29}
30
311Options.prototype.init = function() {
320 if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) {
330 throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate");
34 }
35
36 // Make sure strategy is one of the two allowed
370 if(this.strategy != null && (this.strategy != 'ping' && this.strategy != 'statistical' && this.strategy != 'none'))
380 throw new Error("Only ping or statistical strategies allowed");
39
400 if(this.strategy == null) this.strategy = 'ping';
41
42 // Set logger if strategy exists
430 if(this.strategyInstance) this.strategyInstance.logger = this.logger;
44
45 // Unpack read Preference
460 var readPreference = this.readPreference;
47 // Validate correctness of Read preferences
480 if(readPreference != null) {
490 if(readPreference != ReadPreference.PRIMARY && readPreference != ReadPreference.PRIMARY_PREFERRED
50 && readPreference != ReadPreference.SECONDARY && readPreference != ReadPreference.SECONDARY_PREFERRED
51 && readPreference != ReadPreference.NEAREST && typeof readPreference != 'object' && readPreference['_type'] != 'ReadPreference') {
520 throw new Error("Illegal readPreference mode specified, " + readPreference);
53 }
54
550 this.readPreference = readPreference;
56 } else {
570 this.readPreference = null;
58 }
59
60 // Ensure read_secondary is set correctly
610 if(this.readSecondary != null)
620 this.readSecondary = this.readPreference == ReadPreference.PRIMARY
63 || this.readPreference == false
64 || this.readPreference == null ? false : true;
65
66 // Ensure correct slave set
670 if(this.readSecondary) this.slaveOk = true;
68
69 // Set up logger if any set
700 this.logger = this.logger != null
71 && (typeof this.logger.debug == 'function')
72 && (typeof this.logger.error == 'function')
73 && (typeof this.logger.debug == 'function')
74 ? this.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}};
75
76 // Connection timeout
770 this.connectTimeoutMS = this.socketOptions.connectTimeoutMS
78 ? this.socketOptions.connectTimeoutMS
79 : 1000;
80
81 // Socket connection timeout
820 this.socketTimeoutMS = this.socketOptions.socketTimeoutMS
83 ? this.socketOptions.socketTimeoutMS
84 : 30000;
85}
86
871Options.prototype.decorateAndClean = function(servers, callBackStore) {
880 var self = this;
89
90 // var de duplicate list
910 var uniqueServers = {};
92 // De-duplicate any servers in the seed list
930 for(var i = 0; i < servers.length; i++) {
940 var server = servers[i];
95 // If server does not exist set it
960 if(uniqueServers[server.host + ":" + server.port] == null) {
970 uniqueServers[server.host + ":" + server.port] = server;
98 }
99 }
100
101 // Let's set the deduplicated list of servers
1020 var finalServers = [];
103 // Add the servers
1040 for(var key in uniqueServers) {
1050 finalServers.push(uniqueServers[key]);
106 }
107
1080 finalServers.forEach(function(server) {
109 // Ensure no server has reconnect on
1100 server.options.auto_reconnect = false;
111 // Set up ssl options
1120 server.ssl = self.ssl;
1130 server.sslValidate = self.sslValidate;
1140 server.sslCA = self.sslCA;
1150 server.sslCert = self.sslCert;
1160 server.sslKey = self.sslKey;
1170 server.sslPass = self.sslPass;
1180 server.poolSize = self.poolSize;
119 // Set callback store
1200 server._callBackStore = callBackStore;
121 });
122
1230 return finalServers;
124}
125
1261exports.Options = Options;
127

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js

13%
338
44
294
LineHitsSource
11var ReadPreference = require('../read_preference').ReadPreference
2 , DbCommand = require('../../commands/db_command').DbCommand
3 , inherits = require('util').inherits
4 , format = require('util').format
5 , timers = require('timers')
6 , Server = require('../server').Server
7 , utils = require('../../utils')
8 , PingStrategy = require('./strategies/ping_strategy').PingStrategy
9 , StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy
10 , Options = require('./options').Options
11 , ReplSetState = require('./repl_set_state').ReplSetState
12 , HighAvailabilityProcess = require('./ha').HighAvailabilityProcess
13 , Base = require('../base').Base;
14
151var STATE_STARTING_PHASE_1 = 0;
161var STATE_PRIMARY = 1;
171var STATE_SECONDARY = 2;
181var STATE_RECOVERING = 3;
191var STATE_FATAL_ERROR = 4;
201var STATE_STARTING_PHASE_2 = 5;
211var STATE_UNKNOWN = 6;
221var STATE_ARBITER = 7;
231var STATE_DOWN = 8;
241var STATE_ROLLBACK = 9;
25
26// Set processor, setImmediate if 0.10 otherwise nextTick
271var processor = require('../../utils').processor();
28
29/**
30 * ReplSet constructor provides replicaset functionality
31 *
32 * Options
33 * - **ha** {Boolean, default:true}, turn on high availability.
34 * - **haInterval** {Number, default:2000}, time between each replicaset status check.
35 * - **reconnectWait** {Number, default:1000}, time to wait in miliseconds before attempting reconnect.
36 * - **retries** {Number, default:30}, number of times to attempt a replicaset reconnect.
37 * - **rs_name** {String}, the name of the replicaset to connect to.
38 * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number))
39 * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
40 * - **strategy** {String, default:'ping'}, selection strategy for reads choose between (ping, statistical and none, default is ping)
41 * - **secondaryAcceptableLatencyMS** {Number, default:15}, sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms)
42 * - **connectWithNoPrimary** {Boolean, default:false}, sets if the driver should connect even if no primary is available
43 * - **connectArbiter** {Boolean, default:false}, sets if the driver should connect to arbiters or not.
44 * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**.
45 * - **poolSize** {Number, default:5}, number of connections in the connection pool for each server instance, set to 5 as default for legacy reasons.
46 * - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support)
47 * - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
48 * - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
49 * - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
50 * - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
51 * - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher)
52 *
53 * @class Represents a
54 Replicaset Configuration
55 * @param {Array} list of server objects participating in the replicaset.
56 * @param {Object} [options] additional options for the replicaset connection.
57 */
581var ReplSet = exports.ReplSet = function(servers, options) {
59 // Set up basic
600 if(!(this instanceof ReplSet))
610 return new ReplSet(servers, options);
62
63 // Set up event emitter
640 Base.call(this);
65
66 // Ensure we have a list of servers
670 if(!Array.isArray(servers)) throw Error("The parameter must be an array of servers and contain at least one server");
68 // Ensure no Mongos's
690 for(var i = 0; i < servers.length; i++) {
700 if(!(servers[i] instanceof Server)) throw new Error("list of servers must be of type Server");
71 }
72
73 // Save the options
740 this.options = new Options(options);
75 // Ensure basic validation of options
760 this.options.init();
77
78 // Server state
790 this._serverState = ReplSet.REPLSET_DISCONNECTED;
80 // Add high availability process
810 this._haProcess = new HighAvailabilityProcess(this, this.options);
82
83 // Let's iterate over all the provided server objects and decorate them
840 this.servers = this.options.decorateAndClean(servers, this._callBackStore);
85 // Throw error if no seed servers
860 if(this.servers.length == 0) throw new Error("No valid seed servers in the array");
87
88 // Let's set up our strategy object for picking secondaries
890 if(this.options.strategy == 'ping') {
90 // Create a new instance
910 this.strategyInstance = new PingStrategy(this, this.options.secondaryAcceptableLatencyMS);
920 } else if(this.options.strategy == 'statistical') {
93 // Set strategy as statistical
940 this.strategyInstance = new StatisticsStrategy(this);
95 // Add enable query information
960 this.enableRecordQueryStats(true);
97 }
98
990 this.emitOpen = this.options.emitOpen || true;
100 // Set up a clean state
1010 this._state = new ReplSetState(this);
102 // Current round robin selected server
1030 this._currentServerChoice = 0;
104 // Ensure up the server callbacks
1050 for(var i = 0; i < this.servers.length; i++) {
1060 this.servers[i]._callBackStore = this._callBackStore;
1070 this.servers[i].name = format("%s:%s", this.servers[i].host, this.servers[i].port)
1080 this.servers[i].replicasetInstance = this;
1090 this.servers[i].options.auto_reconnect = false;
1100 this.servers[i].inheritReplSetOptionsFrom(this);
111 }
112
113 // Allow setting the socketTimeoutMS on all connections
114 // to work around issues such as secondaries blocking due to compaction
1150 utils.setSocketTimeoutProperty(this, this.options.socketOptions);
116}
117
118/**
119 * @ignore
120 */
1211inherits(ReplSet, Base);
122
123// Replicaset states
1241ReplSet.REPLSET_CONNECTING = 'connecting';
1251ReplSet.REPLSET_DISCONNECTED = 'disconnected';
1261ReplSet.REPLSET_CONNECTED = 'connected';
1271ReplSet.REPLSET_RECONNECTING = 'reconnecting';
1281ReplSet.REPLSET_DESTROYED = 'destroyed';
1291ReplSet.REPLSET_READ_ONLY = 'readonly';
130
1311ReplSet.prototype.isAutoReconnect = function() {
1320 return true;
133}
134
1351ReplSet.prototype.canWrite = function() {
1360 return this._state.master && this._state.master.isConnected();
137}
138
1391ReplSet.prototype.canRead = function(read) {
1400 if((read == ReadPreference.PRIMARY
1410 || read == null || read == false) && (this._state.master == null || !this._state.master.isConnected())) return false;
1420 return Object.keys(this._state.secondaries).length > 0;
143}
144
145/**
146 * @ignore
147 */
1481ReplSet.prototype.enableRecordQueryStats = function(enable) {
149 // Set the global enable record query stats
1500 this.recordQueryStats = enable;
151
152 // Enable all the servers
1530 for(var i = 0; i < this.servers.length; i++) {
1540 this.servers[i].enableRecordQueryStats(enable);
155 }
156}
157
158/**
159 * @ignore
160 */
1611ReplSet.prototype.setReadPreference = function(preference) {
1620 this.options.readPreference = preference;
163}
164
1651ReplSet.prototype.connect = function(parent, options, callback) {
1660 if(this._serverState != ReplSet.REPLSET_DISCONNECTED)
1670 return callback(new Error("in process of connection"));
168
169 // If no callback throw
1700 if(!(typeof callback == 'function'))
1710 throw new Error("cannot call ReplSet.prototype.connect with no callback function");
172
1730 var self = this;
174 // Save db reference
1750 this.options.db = parent;
176 // Set replicaset as connecting
1770 this._serverState = ReplSet.REPLSET_CONNECTING
178 // Copy all the servers to our list of seeds
1790 var candidateServers = this.servers.slice(0);
180 // Pop the first server
1810 var server = candidateServers.pop();
1820 server.name = format("%s:%s", server.host, server.port);
183 // Set up the options
1840 var opts = {
185 returnIsMasterResults: true,
186 eventReceiver: server
187 }
188
189 // Register some event listeners
1900 this.once("fullsetup", function(err, db, replset) {
191 // Set state to connected
1920 self._serverState = ReplSet.REPLSET_CONNECTED;
193 // Stop any process running
1940 if(self._haProcess) self._haProcess.stop();
195 // Start the HA process
1960 self._haProcess.start();
197
198 // Emit fullsetup
1990 processor(function() {
2000 if(self.emitOpen)
2010 self._emitAcrossAllDbInstances(self, null, "open", null, null, null);
202
2030 self._emitAcrossAllDbInstances(self, null, "fullsetup", null, null, null);
204 });
205
206 // If we have a strategy defined start it
2070 if(self.strategyInstance) {
2080 self.strategyInstance.start();
209 }
210
211 // Finishing up the call
2120 callback(err, db, replset);
213 });
214
215 // Errors
2160 this.once("connectionError", function(err, result) {
2170 callback(err, result);
218 });
219
220 // Attempt to connect to the server
2210 server.connect(this.options.db, opts, _connectHandler(this, candidateServers, server));
222}
223
2241ReplSet.prototype.close = function(callback) {
2250 var self = this;
226 // Set as destroyed
2270 this._serverState = ReplSet.REPLSET_DESTROYED;
228 // Stop the ha
2290 this._haProcess.stop();
230
231 // If we have a strategy stop it
2320 if(this.strategyInstance) {
2330 this.strategyInstance.stop();
234 }
235
236 // Kill all servers available
2370 for(var name in this._state.addresses) {
2380 this._state.addresses[name].close();
239 }
240
241 // Clean out the state
2420 this._state = new ReplSetState(this);
243
244 // Emit close event
2450 processor(function() {
2460 self._emitAcrossAllDbInstances(self, null, "close", null, null, true)
247 });
248
249 // Flush out any remaining call handlers
2500 self._flushAllCallHandlers(utils.toError("Connection Closed By Application"));
251
252 // Callback
2530 if(typeof callback == 'function')
2540 return callback(null, null);
255}
256
257/**
258 * Creates a new server for the `replset` based on `host`.
259 *
260 * @param {String} host - host:port pair (localhost:27017)
261 * @param {ReplSet} replset - the ReplSet instance
262 * @return {Server}
263 * @ignore
264 */
2651var createServer = function(self, host, options) {
266 // copy existing socket options to new server
2670 var socketOptions = {}
2680 if(options.socketOptions) {
2690 var keys = Object.keys(options.socketOptions);
2700 for(var k = 0; k < keys.length; k++) {
2710 socketOptions[keys[k]] = options.socketOptions[keys[k]];
272 }
273 }
274
2750 var parts = host.split(/:/);
2760 if(1 === parts.length) {
2770 parts[1] = Connection.DEFAULT_PORT;
278 }
279
2800 socketOptions.host = parts[0];
2810 socketOptions.port = parseInt(parts[1], 10);
282
2830 var serverOptions = {
284 readPreference: options.readPreference,
285 socketOptions: socketOptions,
286 poolSize: options.poolSize,
287 logger: options.logger,
288 auto_reconnect: false,
289 ssl: options.ssl,
290 sslValidate: options.sslValidate,
291 sslCA: options.sslCA,
292 sslCert: options.sslCert,
293 sslKey: options.sslKey,
294 sslPass: options.sslPass
295 }
296
2970 var server = new Server(socketOptions.host, socketOptions.port, serverOptions);
298 // Set up shared state
2990 server._callBackStore = self._callBackStore;
3000 server.replicasetInstance = self;
3010 server.enableRecordQueryStats(self.recordQueryStats);
302 // Set up event handlers
3030 server.on("close", _handler("close", self, server));
3040 server.on("error", _handler("error", self, server));
3050 server.on("timeout", _handler("timeout", self, server));
3060 return server;
307}
308
3091var _handler = function(event, self, server) {
3100 return function(err, doc) {
311 // The event happened to a primary
312 // Remove it from play
3130 if(self._state.isPrimary(server)) {
314 // Emit that the primary left the replicaset
3150 self.emit('left', 'primary', server);
316 // Get the current master
3170 var current_master = self._state.master;
3180 self._state.master = null;
3190 self._serverState = ReplSet.REPLSET_READ_ONLY;
320
3210 if(current_master != null) {
322 // Unpack variables
3230 var host = current_master.socketOptions.host;
3240 var port = current_master.socketOptions.port;
325
326 // Fire error on any unknown callbacks
3270 self.__executeAllServerSpecificErrorCallbacks(host, port, err);
328 }
3290 } else if(self._state.isSecondary(server)) {
330 // Emit that a secondary left the replicaset
3310 self.emit('left', 'secondary', server);
332 // Delete from the list
3330 delete self._state.secondaries[server.name];
334 }
335
336 // If there is no more connections left and the setting is not destroyed
337 // set to disconnected
3380 if(Object.keys(self._state.addresses).length == 0
339 && self._serverState != ReplSet.REPLSET_DESTROYED) {
3400 self._serverState = ReplSet.REPLSET_DISCONNECTED;
341
342 // Emit close across all the attached db instances
3430 self._dbStore.emit("close", new Error("replicaset disconnected, no valid servers contactable over tcp"), null, true);
344 }
345
346 // Unpack variables
3470 var host = server.socketOptions.host;
3480 var port = server.socketOptions.port;
349
350 // Fire error on any unknown callbacks
3510 self.__executeAllServerSpecificErrorCallbacks(host, port, err);
352 }
353}
354
3551var locateNewServers = function(self, state, candidateServers, ismaster) {
356 // Retrieve the host
3570 var hosts = ismaster.hosts;
358 // In candidate servers
3590 var inCandidateServers = function(name, candidateServers) {
3600 for(var i = 0; i < candidateServers.length; i++) {
3610 if(candidateServers[i].name == name) return true;
362 }
363
3640 return false;
365 }
366
367 // New servers
3680 var newServers = [];
3690 if(Array.isArray(hosts)) {
370 // Let's go over all the hosts
3710 for(var i = 0; i < hosts.length; i++) {
3720 if(!state.contains(hosts[i])
373 && !inCandidateServers(hosts[i], candidateServers)) {
3740 newServers.push(createServer(self, hosts[i], self.options));
375 }
376 }
377 }
378
379 // Return list of possible new servers
3800 return newServers;
381}
382
3831var _connectHandler = function(self, candidateServers, instanceServer) {
3840 return function(err, doc) {
385 // If we have an error add to the list
3860 if(err) {
3870 self._state.errors[instanceServer.name] = instanceServer;
388 } else {
3890 delete self._state.errors[instanceServer.name];
390 }
391
3920 if(!err) {
3930 var ismaster = doc.documents[0]
394
395 // Error the server if
3960 if(!ismaster.ismaster
397 && !ismaster.secondary) {
3980 self._state.errors[instanceServer.name] = instanceServer;
399 }
400 }
401
402
403 // No error let's analyse the ismaster command
4040 if(!err && self._state.errors[instanceServer.name] == null) {
4050 var ismaster = doc.documents[0]
406
407 // If no replicaset name exists set the current one
4080 if(self.options.rs_name == null) {
4090 self.options.rs_name = ismaster.setName;
410 }
411
412 // If we have a member that is not part of the set let's finish up
4130 if(typeof ismaster.setName == 'string' && ismaster.setName != self.options.rs_name) {
4140 return self.emit("connectionError", new Error("Replicaset name " + ismaster.setName + " does not match specified name " + self.options.rs_name));
415 }
416
417 // Add the error handlers
4180 instanceServer.on("close", _handler("close", self, instanceServer));
4190 instanceServer.on("error", _handler("error", self, instanceServer));
4200 instanceServer.on("timeout", _handler("timeout", self, instanceServer));
421
422 // Set any tags on the instance server
4230 instanceServer.name = ismaster.me;
4240 instanceServer.tags = ismaster.tags;
425
426 // Add the server to the list
4270 self._state.addServer(instanceServer, ismaster);
428
429 // Check if we have more servers to add (only check when done with initial set)
4300 if(candidateServers.length == 0) {
431 // Get additional new servers that are not currently in set
4320 var new_servers = locateNewServers(self, self._state, candidateServers, ismaster);
433
434 // Locate any new servers that have not errored out yet
4350 for(var i = 0; i < new_servers.length; i++) {
4360 if(self._state.errors[new_servers[i].name] == null) {
4370 candidateServers.push(new_servers[i])
438 }
439 }
440 }
441 }
442
443 // If the candidate server list is empty and no valid servers
4440 if(candidateServers.length == 0 &&
445 !self._state.hasValidServers()) {
4460 return self.emit("connectionError", new Error("No valid replicaset instance servers found"));
4470 } else if(candidateServers.length == 0) {
4480 if(!self.options.connectWithNoPrimary && (self._state.master == null || !self._state.master.isConnected())) {
4490 return self.emit("connectionError", new Error("No primary found in set"));
450 }
4510 return self.emit("fullsetup", null, self.options.db, self);
452 }
453
454 // Let's connect the next server
4550 var nextServer = candidateServers.pop();
456
457 // Set up the options
4580 var opts = {
459 returnIsMasterResults: true,
460 eventReceiver: nextServer
461 }
462
463 // Attempt to connect to the server
4640 nextServer.connect(self.options.db, opts, _connectHandler(self, candidateServers, nextServer));
465 }
466}
467
4681ReplSet.prototype.isDestroyed = function() {
4690 return this._serverState == ReplSet.REPLSET_DESTROYED;
470}
471
4721ReplSet.prototype.isConnected = function(read) {
4730 var isConnected = false;
474
4750 if(read == null || read == ReadPreference.PRIMARY || read == false)
4760 isConnected = this._state.master != null && this._state.master.isConnected();
477
4780 if((read == ReadPreference.PRIMARY_PREFERRED || read == ReadPreference.SECONDARY_PREFERRED || read == ReadPreference.NEAREST)
479 && ((this._state.master != null && this._state.master.isConnected())
480 || (this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0))) {
4810 isConnected = true;
4820 } else if(read == ReadPreference.SECONDARY) {
4830 isConnected = this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0;
484 }
485
486 // No valid connection return false
4870 return isConnected;
488}
489
4901ReplSet.prototype.isMongos = function() {
4910 return false;
492}
493
4941ReplSet.prototype.checkoutWriter = function() {
4950 if(this._state.master) return this._state.master.checkoutWriter();
4960 return new Error("no writer connection available");
497}
498
4991ReplSet.prototype.processIsMaster = function(_server, _ismaster) {
500 // Server in recovery mode, remove it from available servers
5010 if(!_ismaster.ismaster && !_ismaster.secondary) {
502 // Locate the actual server
5030 var server = this._state.addresses[_server.name];
504 // Close the server, simulating the closing of the connection
505 // to get right removal semantics
5060 if(server) server.close();
507 // Execute any callback errors
5080 _handler(null, this, server)(new Error("server is in recovery mode"));
509 }
510}
511
5121ReplSet.prototype.allRawConnections = function() {
5130 var connections = [];
514
5150 for(var name in this._state.addresses) {
5160 connections = connections.concat(this._state.addresses[name].allRawConnections());
517 }
518
5190 return connections;
520}
521
522/**
523 * @ignore
524 */
5251ReplSet.prototype.allServerInstances = function() {
5260 var self = this;
527 // If no state yet return empty
5280 if(!self._state) return [];
529 // Close all the servers (concatenate entire list of servers first for ease)
5300 var allServers = self._state.master != null ? [self._state.master] : [];
531
532 // Secondary keys
5330 var keys = Object.keys(self._state.secondaries);
534 // Add all secondaries
5350 for(var i = 0; i < keys.length; i++) {
5360 allServers.push(self._state.secondaries[keys[i]]);
537 }
538
539 // Return complete list of all servers
5400 return allServers;
541}
542
543/**
544 * @ignore
545 */
5461ReplSet.prototype.checkoutReader = function(readPreference, tags) {
5470 var connection = null;
548
549 // If we have a read preference object unpack it
5500 if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') {
551 // Validate if the object is using a valid mode
5520 if(!readPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + readPreference.mode);
553 // Set the tag
5540 tags = readPreference.tags;
5550 readPreference = readPreference.mode;
5560 } else if(typeof readPreference == 'object' && readPreference['_type'] != 'ReadPreference') {
5570 return new Error("read preferences must be either a string or an instance of ReadPreference");
558 }
559
560 // Set up our read Preference, allowing us to override the readPreference
5610 var finalReadPreference = readPreference != null ? readPreference : this.options.readPreference;
562
563 // Ensure we unpack a reference
5640 if(finalReadPreference != null && typeof finalReadPreference == 'object' && finalReadPreference['_type'] == 'ReadPreference') {
565 // Validate if the object is using a valid mode
5660 if(!finalReadPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + finalReadPreference.mode);
567 // Set the tag
5680 tags = finalReadPreference.tags;
5690 readPreference = finalReadPreference.mode;
570 }
571
572 // Finalize the read preference setup
5730 finalReadPreference = finalReadPreference == true ? ReadPreference.SECONDARY_PREFERRED : finalReadPreference;
5740 finalReadPreference = finalReadPreference == null ? ReadPreference.PRIMARY : finalReadPreference;
575
576 // If we are reading from a primary
5770 if(finalReadPreference == 'primary') {
578 // If we provide a tags set send an error
5790 if(typeof tags == 'object' && tags != null) {
5800 return new Error("PRIMARY cannot be combined with tags");
581 }
582
583 // If we provide a tags set send an error
5840 if(this._state.master == null) {
5850 return new Error("No replica set primary available for query with ReadPreference PRIMARY");
586 }
587
588 // Checkout a writer
5890 return this.checkoutWriter();
590 }
591
592 // If we have specified to read from a secondary server grab a random one and read
593 // from it, otherwise just pass the primary connection
5940 if((this.options.readSecondary || finalReadPreference == ReadPreference.SECONDARY_PREFERRED || finalReadPreference == ReadPreference.SECONDARY) && Object.keys(this._state.secondaries).length > 0) {
595 // If we have tags, look for servers matching the specific tag
5960 if(this.strategyInstance != null) {
597 // Only pick from secondaries
5980 var _secondaries = [];
5990 for(var key in this._state.secondaries) {
6000 _secondaries.push(this._state.secondaries[key]);
601 }
602
6030 if(finalReadPreference == ReadPreference.SECONDARY) {
604 // Check out the nearest from only the secondaries
6050 connection = this.strategyInstance.checkoutConnection(tags, _secondaries);
606 } else {
6070 connection = this.strategyInstance.checkoutConnection(tags, _secondaries);
608 // No candidate servers that match the tags, error
6090 if(connection == null || connection instanceof Error) {
610 // No secondary server avilable, attemp to checkout a primary server
6110 connection = this.checkoutWriter();
612 // If no connection return an error
6130 if(connection == null || connection instanceof Error) {
6140 return new Error("No replica set members available for query");
615 }
616 }
617 }
6180 } else if(tags != null && typeof tags == 'object') {
619 // Get connection
6200 connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) {
621 // No candidate servers that match the tags, error
6220 if(connection == null) {
6230 return new Error("No replica set members available for query");
624 }
625 } else {
6260 connection = _roundRobin(this, tags);
627 }
6280 } else if(finalReadPreference == ReadPreference.PRIMARY_PREFERRED) {
629 // Check if there is a primary available and return that if possible
6300 connection = this.checkoutWriter();
631 // If no connection available checkout a secondary
6320 if(connection == null || connection instanceof Error) {
633 // If we have tags, look for servers matching the specific tag
6340 if(tags != null && typeof tags == 'object') {
635 // Get connection
6360 connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) {
637 // No candidate servers that match the tags, error
6380 if(connection == null) {
6390 return new Error("No replica set members available for query");
640 }
641 } else {
6420 connection = _roundRobin(this, tags);
643 }
644 }
6450 } else if(finalReadPreference == ReadPreference.SECONDARY_PREFERRED) {
646 // If we have tags, look for servers matching the specific tag
6470 if(this.strategyInstance != null) {
6480 connection = this.strategyInstance.checkoutConnection(tags);
649
650 // No candidate servers that match the tags, error
6510 if(connection == null || connection instanceof Error) {
652 // No secondary server avilable, attemp to checkout a primary server
6530 connection = this.checkoutWriter();
654 // If no connection return an error
6550 if(connection == null || connection instanceof Error) {
6560 var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference;
6570 return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
658 }
659 }
6600 } else if(tags != null && typeof tags == 'object') {
661 // Get connection
6620 connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) {
663 // No candidate servers that match the tags, error
6640 if(connection == null) {
665 // No secondary server avilable, attemp to checkout a primary server
6660 connection = this.checkoutWriter();
667 // If no connection return an error
6680 if(connection == null || connection instanceof Error) {
6690 var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference;
6700 return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
671 }
672 }
673 }
6740 } else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance != null) {
6750 connection = this.strategyInstance.checkoutConnection(tags);
6760 } else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance == null) {
6770 return new Error("A strategy for calculating nearness must be enabled such as ping or statistical");
6780 } else if(finalReadPreference == ReadPreference.SECONDARY && Object.keys(this._state.secondaries).length == 0) {
6790 if(tags != null && typeof tags == 'object') {
6800 var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference;
6810 return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
682 } else {
6830 return new Error("No replica set secondary available for query with ReadPreference SECONDARY");
684 }
685 } else {
6860 connection = this.checkoutWriter();
687 }
688
689 // Return the connection
6900 return connection;
691}
692
693/**
694 * @ignore
695 */
6961var _pickFromTags = function(self, tags) {
697 // If we have an array or single tag selection
6980 var tagObjects = Array.isArray(tags) ? tags : [tags];
699 // Iterate over all tags until we find a candidate server
7000 for(var _i = 0; _i < tagObjects.length; _i++) {
701 // Grab a tag object
7020 var tagObject = tagObjects[_i];
703 // Matching keys
7040 var matchingKeys = Object.keys(tagObject);
705 // Match all the servers that match the provdided tags
7060 var keys = Object.keys(self._state.secondaries);
7070 var candidateServers = [];
708
7090 for(var i = 0; i < keys.length; i++) {
7100 var server = self._state.secondaries[keys[i]];
711 // If we have tags match
7120 if(server.tags != null) {
7130 var matching = true;
714 // Ensure we have all the values
7150 for(var j = 0; j < matchingKeys.length; j++) {
7160 if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) {
7170 matching = false;
7180 break;
719 }
720 }
721
722 // If we have a match add it to the list of matching servers
7230 if(matching) {
7240 candidateServers.push(server);
725 }
726 }
727 }
728
729 // If we have a candidate server return
7300 if(candidateServers.length > 0) {
7310 if(self.strategyInstance) return self.strategyInstance.checkoutConnection(tags, candidateServers);
732 // Set instance to return
7330 return candidateServers[Math.floor(Math.random() * candidateServers.length)].checkoutReader();
734 }
735 }
736
737 // No connection found
7380 return null;
739}
740
741/**
742 * Pick a secondary using round robin
743 *
744 * @ignore
745 */
7461function _roundRobin (replset, tags) {
7470 var keys = Object.keys(replset._state.secondaries);
748 // Update index
7490 replset._currentServerChoice = replset._currentServerChoice + 1;
750 // Pick a server
7510 var key = keys[replset._currentServerChoice % keys.length];
752
7530 var conn = null != replset._state.secondaries[key]
754 ? replset._state.secondaries[key].checkoutReader()
755 : null;
756
757 // If connection is null fallback to first available secondary
7580 if(null == conn) {
7590 conn = pickFirstConnectedSecondary(replset, tags);
760 }
761
7620 return conn;
763}
764
765/**
766 * @ignore
767 */
7681var pickFirstConnectedSecondary = function pickFirstConnectedSecondary(self, tags) {
7690 var keys = Object.keys(self._state.secondaries);
7700 var connection;
771
772 // Find first available reader if any
7730 for(var i = 0; i < keys.length; i++) {
7740 connection = self._state.secondaries[keys[i]].checkoutReader();
7750 if(connection) return connection;
776 }
777
778 // If we still have a null, read from primary if it's not secondary only
7790 if(self._readPreference == ReadPreference.SECONDARY_PREFERRED) {
7800 connection = self._state.master.checkoutReader();
7810 if(connection) return connection;
782 }
783
7840 var preferenceName = self._readPreference == ReadPreference.SECONDARY_PREFERRED
785 ? 'secondary'
786 : self._readPreference;
787
7880 return new Error("No replica set member available for query with ReadPreference "
789 + preferenceName + " and tags " + JSON.stringify(tags));
790}
791
792/**
793 * Get list of secondaries
794 * @ignore
795 */
7961Object.defineProperty(ReplSet.prototype, "secondaries", {enumerable: true
797 , get: function() {
7980 return utils.objectToArray(this._state.secondaries);
799 }
800});
801
802/**
803 * Get list of secondaries
804 * @ignore
805 */
8061Object.defineProperty(ReplSet.prototype, "arbiters", {enumerable: true
807 , get: function() {
8080 return utils.objectToArray(this._state.arbiters);
809 }
810});
811
812

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js

17%
46
8
38
LineHitsSource
1/**
2 * Interval state object constructor
3 *
4 * @ignore
5 */
61var ReplSetState = function ReplSetState (replset) {
70 this.errorMessages = [];
80 this.secondaries = {};
90 this.addresses = {};
100 this.arbiters = {};
110 this.passives = {};
120 this.members = [];
130 this.errors = {};
140 this.setName = null;
150 this.master = null;
160 this.replset = replset;
17}
18
191ReplSetState.prototype.hasValidServers = function() {
200 var validServers = [];
210 if(this.master && this.master.isConnected()) return true;
22
230 if(this.secondaries) {
240 var keys = Object.keys(this.secondaries)
250 for(var i = 0; i < keys.length; i++) {
260 if(this.secondaries[keys[i]].isConnected())
270 return true;
28 }
29 }
30
310 return false;
32}
33
341ReplSetState.prototype.getAllReadServers = function() {
350 var candidate_servers = [];
360 for(var name in this.addresses) {
370 candidate_servers.push(this.addresses[name]);
38 }
39
40 // Return all possible read candidates
410 return candidate_servers;
42}
43
441ReplSetState.prototype.addServer = function(server, master) {
450 server.name = master.me;
46
470 if(master.ismaster) {
480 this.master = server;
490 this.addresses[server.name] = server;
500 this.replset.emit('joined', "primary", master, server);
510 } else if(master.secondary) {
520 this.secondaries[server.name] = server;
530 this.addresses[server.name] = server;
540 this.replset.emit('joined', "secondary", master, server);
550 } else if(master.arbiters) {
560 this.arbiters[server.name] = server;
570 this.addresses[server.name] = server;
580 this.replset.emit('joined', "arbiter", master, server);
59 }
60}
61
621ReplSetState.prototype.contains = function(host) {
630 return this.addresses[host] != null;
64}
65
661ReplSetState.prototype.isPrimary = function(server) {
670 return this.master && this.master.name == server.name;
68}
69
701ReplSetState.prototype.isSecondary = function(server) {
710 return this.secondaries[server.name] != null;
72}
73
741exports.ReplSetState = ReplSetState;
75

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js

4%
145
6
139
LineHitsSource
11var Server = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/../../server").Server
2 , format = require('util').format;
3
4// The ping strategy uses pings each server and records the
5// elapsed time for the server so it can pick a server based on lowest
6// return time for the db command {ping:true}
71var PingStrategy = exports.PingStrategy = function(replicaset, secondaryAcceptableLatencyMS) {
80 this.replicaset = replicaset;
90 this.secondaryAcceptableLatencyMS = secondaryAcceptableLatencyMS;
100 this.state = 'disconnected';
110 this.pingInterval = 5000;
12 // Class instance
130 this.Db = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/../../../db").Db;
14 // Active db connections
150 this.dbs = {};
16 // Current server index
170 this.index = 0;
18 // Logger api
190 this.Logger = null;
20}
21
22// Starts any needed code
231PingStrategy.prototype.start = function(callback) {
24 // already running?
250 if ('connected' == this.state) return;
26
270 this.state = 'connected';
28
29 // Start ping server
300 this._pingServer(callback);
31}
32
33// Stops and kills any processes running
341PingStrategy.prototype.stop = function(callback) {
35 // Stop the ping process
360 this.state = 'disconnected';
37
38 // Stop all the server instances
390 for(var key in this.dbs) {
400 this.dbs[key].close();
41 }
42
43 // optional callback
440 callback && callback(null, null);
45}
46
471PingStrategy.prototype.checkoutConnection = function(tags, secondaryCandidates) {
48 // Servers are picked based on the lowest ping time and then servers that lower than that + secondaryAcceptableLatencyMS
49 // Create a list of candidat servers, containing the primary if available
500 var candidateServers = [];
510 var self = this;
52
53 // If we have not provided a list of candidate servers use the default setup
540 if(!Array.isArray(secondaryCandidates)) {
550 candidateServers = this.replicaset._state.master != null ? [this.replicaset._state.master] : [];
56 // Add all the secondaries
570 var keys = Object.keys(this.replicaset._state.secondaries);
580 for(var i = 0; i < keys.length; i++) {
590 candidateServers.push(this.replicaset._state.secondaries[keys[i]])
60 }
61 } else {
620 candidateServers = secondaryCandidates;
63 }
64
65 // Final list of eligable server
660 var finalCandidates = [];
67
68 // If we have tags filter by tags
690 if(tags != null && typeof tags == 'object') {
70 // If we have an array or single tag selection
710 var tagObjects = Array.isArray(tags) ? tags : [tags];
72 // Iterate over all tags until we find a candidate server
730 for(var _i = 0; _i < tagObjects.length; _i++) {
74 // Grab a tag object
750 var tagObject = tagObjects[_i];
76 // Matching keys
770 var matchingKeys = Object.keys(tagObject);
78 // Remove any that are not tagged correctly
790 for(var i = 0; i < candidateServers.length; i++) {
800 var server = candidateServers[i];
81 // If we have tags match
820 if(server.tags != null) {
830 var matching = true;
84
85 // Ensure we have all the values
860 for(var j = 0; j < matchingKeys.length; j++) {
870 if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) {
880 matching = false;
890 break;
90 }
91 }
92
93 // If we have a match add it to the list of matching servers
940 if(matching) {
950 finalCandidates.push(server);
96 }
97 }
98 }
99 }
100 } else {
101 // Final array candidates
1020 var finalCandidates = candidateServers;
103 }
104
105 // Sort by ping time
1060 finalCandidates.sort(function(a, b) {
1070 return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs'];
108 });
109
1100 if(0 === finalCandidates.length)
1110 return new Error("No replica set members available for query");
112
113 // find lowest server with a ping time
1140 var lowest = finalCandidates.filter(function (server) {
1150 return undefined != server.runtimeStats.pingMs;
116 })[0];
117
1180 if(!lowest) {
1190 lowest = finalCandidates[0];
120 }
121
122 // convert to integer
1230 var lowestPing = lowest.runtimeStats.pingMs | 0;
124
125 // determine acceptable latency
1260 var acceptable = lowestPing + this.secondaryAcceptableLatencyMS;
127
128 // remove any server responding slower than acceptable
1290 var len = finalCandidates.length;
1300 while(len--) {
1310 if(finalCandidates[len].runtimeStats['pingMs'] > acceptable) {
1320 finalCandidates.splice(len, 1);
133 }
134 }
135
1360 if(self.logger && self.logger.debug) {
1370 self.logger.debug("Ping strategy selection order for tags", tags);
1380 finalCandidates.forEach(function(c) {
1390 self.logger.debug(format("%s:%s = %s ms", c.host, c.port, c.runtimeStats['pingMs']), null);
140 })
141 }
142
143 // If no candidates available return an error
1440 if(finalCandidates.length == 0)
1450 return new Error("No replica set members available for query");
146
147 // Ensure no we don't overflow
1480 this.index = this.index % finalCandidates.length
149 // Pick a random acceptable server
1500 var connection = finalCandidates[this.index].checkoutReader();
151 // Point to next candidate (round robin style)
1520 this.index = this.index + 1;
153
1540 if(self.logger && self.logger.debug) {
1550 if(connection)
1560 self.logger.debug("picked server %s:%s", connection.socketOptions.host, connection.socketOptions.port);
157 }
158
1590 return connection;
160}
161
1621PingStrategy.prototype._pingServer = function(callback) {
1630 var self = this;
164
165 // Ping server function
1660 var pingFunction = function() {
167 // Our state changed to disconnected or destroyed return
1680 if(self.state == 'disconnected' || self.state == 'destroyed') return;
169 // If the replicaset is destroyed return
1700 if(self.replicaset.isDestroyed() || self.replicaset._serverState == 'disconnected') return
171
172 // Create a list of all servers we can send the ismaster command to
1730 var allServers = self.replicaset._state.master != null ? [self.replicaset._state.master] : [];
174
175 // Secondary keys
1760 var keys = Object.keys(self.replicaset._state.secondaries);
177 // Add all secondaries
1780 for(var i = 0; i < keys.length; i++) {
1790 allServers.push(self.replicaset._state.secondaries[keys[i]]);
180 }
181
182 // Number of server entries
1830 var numberOfEntries = allServers.length;
184
185 // We got keys
1860 for(var i = 0; i < allServers.length; i++) {
187
188 // We got a server instance
1890 var server = allServers[i];
190
191 // Create a new server object, avoid using internal connections as they might
192 // be in an illegal state
1930 new function(serverInstance) {
1940 var _db = self.dbs[serverInstance.host + ":" + serverInstance.port];
195 // If we have a db
1960 if(_db != null) {
197 // Startup time of the command
1980 var startTime = Date.now();
199
200 // Execute ping command in own scope
2010 var _ping = function(__db, __serverInstance) {
202 // Execute ping on this connection
2030 __db.executeDbCommand({ping:1}, {failFast:true}, function(err) {
2040 if(err) {
2050 delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port];
2060 __db.close();
2070 return done();
208 }
209
2100 if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) {
2110 __serverInstance.runtimeStats['pingMs'] = Date.now() - startTime;
212 }
213
2140 __db.executeDbCommand({ismaster:1}, {failFast:true}, function(err, result) {
2150 if(err) {
2160 delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port];
2170 __db.close();
2180 return done();
219 }
220
221 // Process the ismaster for the server
2220 if(result && result.documents && self.replicaset.processIsMaster) {
2230 self.replicaset.processIsMaster(__serverInstance, result.documents[0]);
224 }
225
226 // Done with the pinging
2270 done();
228 });
229 });
230 };
231 // Ping
2320 _ping(_db, serverInstance);
233 } else {
2340 var connectTimeoutMS = self.replicaset.options.socketOptions
235 ? self.replicaset.options.socketOptions.connectTimeoutMS : 0
236
237 // Create a new master connection
2380 var _server = new Server(serverInstance.host, serverInstance.port, {
239 auto_reconnect: false,
240 returnIsMasterResults: true,
241 slaveOk: true,
242 poolSize: 1,
243 socketOptions: { connectTimeoutMS: connectTimeoutMS },
244 ssl: self.replicaset.options.ssl,
245 sslValidate: self.replicaset.options.sslValidate,
246 sslCA: self.replicaset.options.sslCA,
247 sslCert: self.replicaset.options.sslCert,
248 sslKey: self.replicaset.options.sslKey,
249 sslPass: self.replicaset.options.sslPass
250 });
251
252 // Create Db instance
2530 var _db = new self.Db('local', _server, { safe: true });
2540 _db.on("close", function() {
2550 delete self.dbs[this.serverConfig.host + ":" + this.serverConfig.port];
256 })
257
2580 var _ping = function(__db, __serverInstance) {
2590 if(self.state == 'disconnected') {
2600 self.stop();
2610 return;
262 }
263
2640 __db.open(function(err, db) {
2650 if(self.state == 'disconnected' && __db != null) {
2660 return __db.close();
267 }
268
2690 if(err) {
2700 delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port];
2710 __db.close();
2720 return done();
273 }
274
275 // Save instance
2760 self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port] = __db;
277
278 // Startup time of the command
2790 var startTime = Date.now();
280
281 // Execute ping on this connection
2820 __db.executeDbCommand({ping:1}, {failFast:true}, function(err) {
2830 if(err) {
2840 delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port];
2850 __db.close();
2860 return done();
287 }
288
2890 if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) {
2900 __serverInstance.runtimeStats['pingMs'] = Date.now() - startTime;
291 }
292
2930 __db.executeDbCommand({ismaster:1}, {failFast:true}, function(err, result) {
2940 if(err) {
2950 delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port];
2960 __db.close();
2970 return done();
298 }
299
300 // Process the ismaster for the server
3010 if(result && result.documents && self.replicaset.processIsMaster) {
3020 self.replicaset.processIsMaster(__serverInstance, result.documents[0]);
303 }
304
305 // Done with the pinging
3060 done();
307 });
308 });
309 });
310 };
311
312 // Ping the server
3130 _ping(_db, serverInstance);
314 }
315
3160 function done() {
317 // Adjust the number of checks
3180 numberOfEntries--;
319
320 // If we are done with all results coming back trigger ping again
3210 if(0 === numberOfEntries && 'connected' == self.state) {
3220 setTimeout(pingFunction, self.pingInterval);
323 }
324 }
325 }(server);
326 }
327 }
328
329 // Start pingFunction
3300 pingFunction();
331
3320 callback && callback(null);
333}
334

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js

11%
34
4
30
LineHitsSource
1// The Statistics strategy uses the measure of each end-start time for each
2// query executed against the db to calculate the mean, variance and standard deviation
3// and pick the server which the lowest mean and deviation
41var StatisticsStrategy = exports.StatisticsStrategy = function(replicaset) {
50 this.replicaset = replicaset;
6 // Logger api
70 this.Logger = null;
8}
9
10// Starts any needed code
111StatisticsStrategy.prototype.start = function(callback) {
120 callback && callback(null, null);
13}
14
151StatisticsStrategy.prototype.stop = function(callback) {
160 callback && callback(null, null);
17}
18
191StatisticsStrategy.prototype.checkoutConnection = function(tags, secondaryCandidates) {
20 // Servers are picked based on the lowest ping time and then servers that lower than that + secondaryAcceptableLatencyMS
21 // Create a list of candidat servers, containing the primary if available
220 var candidateServers = [];
23
24 // If we have not provided a list of candidate servers use the default setup
250 if(!Array.isArray(secondaryCandidates)) {
260 candidateServers = this.replicaset._state.master != null ? [this.replicaset._state.master] : [];
27 // Add all the secondaries
280 var keys = Object.keys(this.replicaset._state.secondaries);
290 for(var i = 0; i < keys.length; i++) {
300 candidateServers.push(this.replicaset._state.secondaries[keys[i]])
31 }
32 } else {
330 candidateServers = secondaryCandidates;
34 }
35
36 // Final list of eligable server
370 var finalCandidates = [];
38
39 // If we have tags filter by tags
400 if(tags != null && typeof tags == 'object') {
41 // If we have an array or single tag selection
420 var tagObjects = Array.isArray(tags) ? tags : [tags];
43 // Iterate over all tags until we find a candidate server
440 for(var _i = 0; _i < tagObjects.length; _i++) {
45 // Grab a tag object
460 var tagObject = tagObjects[_i];
47 // Matching keys
480 var matchingKeys = Object.keys(tagObject);
49 // Remove any that are not tagged correctly
500 for(var i = 0; i < candidateServers.length; i++) {
510 var server = candidateServers[i];
52 // If we have tags match
530 if(server.tags != null) {
540 var matching = true;
55
56 // Ensure we have all the values
570 for(var j = 0; j < matchingKeys.length; j++) {
580 if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) {
590 matching = false;
600 break;
61 }
62 }
63
64 // If we have a match add it to the list of matching servers
650 if(matching) {
660 finalCandidates.push(server);
67 }
68 }
69 }
70 }
71 } else {
72 // Final array candidates
730 var finalCandidates = candidateServers;
74 }
75
76 // If no candidates available return an error
770 if(finalCandidates.length == 0) return new Error("No replica set members available for query");
78 // Pick a random server
790 return finalCandidates[Math.round(Math.random(1000000) * (finalCandidates.length - 1))].checkoutReader();
80}
81

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js

30%
378
117
261
LineHitsSource
11var Connection = require('./connection').Connection,
2 ReadPreference = require('./read_preference').ReadPreference,
3 DbCommand = require('../commands/db_command').DbCommand,
4 MongoReply = require('../responses/mongo_reply').MongoReply,
5 ConnectionPool = require('./connection_pool').ConnectionPool,
6 EventEmitter = require('events').EventEmitter,
7 ServerCapabilities = require('./server_capabilities').ServerCapabilities,
8 Base = require('./base').Base,
9 format = require('util').format,
10 utils = require('../utils'),
11 timers = require('timers'),
12 inherits = require('util').inherits;
13
14// Set processor, setImmediate if 0.10 otherwise nextTick
151var processor = require('../utils').processor();
16
17/**
18 * Class representing a single MongoDB Server connection
19 *
20 * Options
21 * - **readPreference** {String, default:null}, set's the read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST)
22 * - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support)
23 * - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
24 * - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
25 * - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
26 * - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
27 * - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher)
28 * - **poolSize** {Number, default:5}, number of connections in the connection pool, set to 5 as default for legacy reasons.
29 * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number))
30 * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**.
31 * - **auto_reconnect** {Boolean, default:false}, reconnect on error.
32 * - **disableDriverBSONSizeCheck** {Boolean, default:false}, force the server to error if the BSON message is to big
33 *
34 * @class Represents a Server connection.
35 * @param {String} host the server host
36 * @param {Number} port the server port
37 * @param {Object} [options] optional options for insert command
38 */
391function Server(host, port, options) {
40 // Set up Server instance
411 if(!(this instanceof Server)) return new Server(host, port, options);
42
43 // Set up event emitter
441 Base.call(this);
45
46 // Ensure correct values
471 if(port != null && typeof port == 'object') {
480 options = port;
490 port = Connection.DEFAULT_PORT;
50 }
51
521 var self = this;
531 this.host = host;
541 this.port = port;
551 this.options = options == null ? {} : options;
561 this.internalConnection;
571 this.internalMaster = false;
581 this.connected = false;
591 this.poolSize = this.options.poolSize == null ? 5 : this.options.poolSize;
601 this.disableDriverBSONSizeCheck = this.options.disableDriverBSONSizeCheck != null ? this.options.disableDriverBSONSizeCheck : false;
611 this._used = false;
621 this.replicasetInstance = null;
63
64 // Emit open setup
651 this.emitOpen = this.options.emitOpen || true;
66 // Set ssl as connection method
671 this.ssl = this.options.ssl == null ? false : this.options.ssl;
68 // Set ssl validation
691 this.sslValidate = this.options.sslValidate == null ? false : this.options.sslValidate;
70 // Set the ssl certificate authority (array of Buffer/String keys)
711 this.sslCA = Array.isArray(this.options.sslCA) ? this.options.sslCA : null;
72 // Certificate to present to the server
731 this.sslCert = this.options.sslCert;
74 // Certificate private key if in separate file
751 this.sslKey = this.options.sslKey;
76 // Password to unlock private key
771 this.sslPass = this.options.sslPass;
78 // Server capabilities
791 this.serverCapabilities = null;
80 // Set server name
811 this.name = format("%s:%s", host, port);
82
83 // Ensure we are not trying to validate with no list of certificates
841 if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) {
850 throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate");
86 }
87
88 // Get the readPreference
891 var readPreference = this.options['readPreference'];
90 // If readPreference is an object get the mode string
911 var validateReadPreference = readPreference != null && typeof readPreference == 'object' ? readPreference.mode : readPreference;
92 // Read preference setting
931 if(validateReadPreference != null) {
940 if(validateReadPreference != ReadPreference.PRIMARY && validateReadPreference != ReadPreference.SECONDARY && validateReadPreference != ReadPreference.NEAREST
95 && validateReadPreference != ReadPreference.SECONDARY_PREFERRED && validateReadPreference != ReadPreference.PRIMARY_PREFERRED) {
960 throw new Error("Illegal readPreference mode specified, " + validateReadPreference);
97 }
98
99 // Set read Preference
1000 this._readPreference = readPreference;
101 } else {
1021 this._readPreference = null;
103 }
104
105 // Contains the isMaster information returned from the server
1061 this.isMasterDoc;
107
108 // Set default connection pool options
1091 this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {};
1101 if(this.disableDriverBSONSizeCheck) this.socketOptions.disableDriverBSONSizeCheck = this.disableDriverBSONSizeCheck;
111
112 // Set ssl up if it's defined
1131 if(this.ssl) {
1140 this.socketOptions.ssl = true;
115 // Set ssl validation
1160 this.socketOptions.sslValidate = this.sslValidate == null ? false : this.sslValidate;
117 // Set the ssl certificate authority (array of Buffer/String keys)
1180 this.socketOptions.sslCA = Array.isArray(this.sslCA) ? this.sslCA : null;
119 // Set certificate to present
1200 this.socketOptions.sslCert = this.sslCert;
121 // Set certificate to present
1220 this.socketOptions.sslKey = this.sslKey;
123 // Password to unlock private key
1240 this.socketOptions.sslPass = this.sslPass;
125 }
126
127 // Set up logger if any set
1281 this.logger = this.options.logger != null
129 && (typeof this.options.logger.debug == 'function')
130 && (typeof this.options.logger.error == 'function')
131 && (typeof this.options.logger.log == 'function')
132 ? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}};
133
134 // Just keeps list of events we allow
1351 this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[]};
136 // Internal state of server connection
1371 this._serverState = 'disconnected';
138 // Contains state information about server connection
1391 this._state = {'runtimeStats': {'queryStats':new RunningStats()}};
140 // Do we record server stats or not
1411 this.recordQueryStats = false;
142
143 // Allow setting the socketTimeoutMS on all connections
144 // to work around issues such as secondaries blocking due to compaction
1451 utils.setSocketTimeoutProperty(this, this.socketOptions);
146};
147
148/**
149 * @ignore
150 */
1511inherits(Server, Base);
152
153//
154// Deprecated, USE ReadPreferences class
155//
1561Server.READ_PRIMARY = ReadPreference.PRIMARY;
1571Server.READ_SECONDARY = ReadPreference.SECONDARY_PREFERRED;
1581Server.READ_SECONDARY_ONLY = ReadPreference.SECONDARY;
159
160/**
161 * Always ourselves
162 * @ignore
163 */
1641Server.prototype.setReadPreference = function(readPreference) {
1650 this._readPreference = readPreference;
166}
167
168/**
169 * @ignore
170 */
1711Server.prototype.isMongos = function() {
1720 return this.isMasterDoc != null && this.isMasterDoc['msg'] == "isdbgrid" ? true : false;
173}
174
175/**
176 * @ignore
177 */
1781Server.prototype._isUsed = function() {
1791 return this._used;
180}
181
182/**
183 * @ignore
184 */
1851Server.prototype.close = function(callback) {
186 // Set server status as disconnected
1870 this._serverState = 'destroyed';
188 // Remove all local listeners
1890 this.removeAllListeners();
190
1910 if(this.connectionPool != null) {
192 // Remove all the listeners on the pool so it does not fire messages all over the place
1930 this.connectionPool.removeAllEventListeners();
194 // Close the connection if it's open
1950 this.connectionPool.stop(true);
196 }
197
198 // Emit close event
1990 if(this.db && !this.isSetMember()) {
2000 var self = this;
2010 processor(function() {
2020 self._emitAcrossAllDbInstances(self, null, "close", null, null, true)
203 })
204
205 // Flush out any remaining call handlers
2060 self._flushAllCallHandlers(utils.toError("Connection Closed By Application"));
207 }
208
209 // Peform callback if present
2100 if(typeof callback === 'function') callback(null);
211};
212
2131Server.prototype.isDestroyed = function() {
2140 return this._serverState == 'destroyed';
215}
216
217/**
218 * @ignore
219 */
2201Server.prototype.isConnected = function() {
2210 return this.connectionPool != null && this.connectionPool.isConnected();
222}
223
224/**
225 * @ignore
226 */
2271Server.prototype.canWrite = Server.prototype.isConnected;
2281Server.prototype.canRead = Server.prototype.isConnected;
229
2301Server.prototype.isAutoReconnect = function() {
2310 if(this.isSetMember()) return false;
2320 return this.options.auto_reconnect != null ? this.options.auto_reconnect : true;
233}
234
235/**
236 * @ignore
237 */
2381Server.prototype.allServerInstances = function() {
2390 return [this];
240}
241
242/**
243 * @ignore
244 */
2451Server.prototype.isSetMember = function() {
2460 return this.replicasetInstance != null || this.mongosInstance != null;
247}
248
249/**
250 * Assigns a replica set to this `server`.
251 *
252 * @param {ReplSet} replset
253 * @ignore
254 */
2551Server.prototype.assignReplicaSet = function (replset) {
2560 this.replicasetInstance = replset;
2570 this.inheritReplSetOptionsFrom(replset);
2580 this.enableRecordQueryStats(replset.recordQueryStats);
259}
260
261/**
262 * Takes needed options from `replset` and overwrites
263 * our own options.
264 *
265 * @param {ReplSet} replset
266 * @ignore
267 */
2681Server.prototype.inheritReplSetOptionsFrom = function (replset) {
2690 this.socketOptions = {};
2700 this.socketOptions.connectTimeoutMS = replset.options.socketOptions.connectTimeoutMS || 30000;
271
2720 if(replset.options.ssl) {
273 // Set ssl on
2740 this.socketOptions.ssl = true;
275 // Set ssl validation
2760 this.socketOptions.sslValidate = replset.options.sslValidate == null ? false : replset.options.sslValidate;
277 // Set the ssl certificate authority (array of Buffer/String keys)
2780 this.socketOptions.sslCA = Array.isArray(replset.options.sslCA) ? replset.options.sslCA : null;
279 // Set certificate to present
2800 this.socketOptions.sslCert = replset.options.sslCert;
281 // Set certificate to present
2820 this.socketOptions.sslKey = replset.options.sslKey;
283 // Password to unlock private key
2840 this.socketOptions.sslPass = replset.options.sslPass;
285 }
286
287 // If a socket option object exists clone it
2880 if(utils.isObject(replset.options.socketOptions)) {
2890 var keys = Object.keys(replset.options.socketOptions);
2900 for(var i = 0; i < keys.length; i++)
2910 this.socketOptions[keys[i]] = replset.options.socketOptions[keys[i]];
292 }
293}
294
295/**
296 * Opens this server connection.
297 *
298 * @ignore
299 */
3001Server.prototype.connect = function(dbInstance, options, callback) {
3011 if('function' === typeof options) callback = options, options = {};
3021 if(options == null) options = {};
3031 if(!('function' === typeof callback)) callback = null;
3041 var self = this;
305 // Save the options
3061 this.options = options;
307
308 // Currently needed to work around problems with multiple connections in a pool with ssl
309 // TODO fix if possible
3101 if(this.ssl == true) {
311 // Set up socket options for ssl
3120 this.socketOptions.ssl = true;
313 // Set ssl validation
3140 this.socketOptions.sslValidate = this.sslValidate == null ? false : this.sslValidate;
315 // Set the ssl certificate authority (array of Buffer/String keys)
3160 this.socketOptions.sslCA = Array.isArray(this.sslCA) ? this.sslCA : null;
317 // Set certificate to present
3180 this.socketOptions.sslCert = this.sslCert;
319 // Set certificate to present
3200 this.socketOptions.sslKey = this.sslKey;
321 // Password to unlock private key
3220 this.socketOptions.sslPass = this.sslPass;
323 }
324
325 // Let's connect
3261 var server = this;
327 // Let's us override the main receiver of events
3281 var eventReceiver = options.eventReceiver != null ? options.eventReceiver : this;
329 // Save reference to dbInstance
3301 this.db = dbInstance; // `db` property matches ReplSet and Mongos
3311 this.dbInstances = [dbInstance];
332
333 // Force connection pool if there is one
3341 if(server.connectionPool) server.connectionPool.stop();
335 // Set server state to connecting
3361 this._serverState = 'connecting';
337
3381 if(server.connectionPool != null) {
339 // Remove all the listeners on the pool so it does not fire messages all over the place
3400 this.connectionPool.removeAllEventListeners();
341 // Close the connection if it's open
3420 this.connectionPool.stop(true);
343 }
344
3451 this.connectionPool = new ConnectionPool(this.host, this.port, this.poolSize, dbInstance.bson, this.socketOptions);
3461 var connectionPool = this.connectionPool;
347 // If ssl is not enabled don't wait between the pool connections
3482 if(this.ssl == null || !this.ssl) connectionPool._timeToWait = null;
349 // Set logger on pool
3501 connectionPool.logger = this.logger;
3511 connectionPool.bson = dbInstance.bson;
352
353 // Set basic parameters passed in
3541 var returnIsMasterResults = options.returnIsMasterResults == null ? false : options.returnIsMasterResults;
355
356 // Create a default connect handler, overriden when using replicasets
3571 var connectCallback = function(_server) {
3581 return function(err, reply) {
359 // ensure no callbacks get called twice
3600 var internalCallback = callback;
3610 callback = null;
362
363 // Assign the server
3640 _server = _server != null ? _server : server;
365
366 // If something close down the connection and removed the callback before
367 // proxy killed connection etc, ignore the erorr as close event was isssued
3680 if(err != null && internalCallback == null) return;
369 // Internal callback
3700 if(err != null) return internalCallback(err, null, _server);
3710 _server.master = reply.documents[0].ismaster == 1 ? true : false;
3720 _server.connectionPool.setMaxBsonSize(reply.documents[0].maxBsonObjectSize);
3730 _server.connectionPool.setMaxMessageSizeBytes(reply.documents[0].maxMessageSizeBytes);
374 // Set server state to connEcted
3750 _server._serverState = 'connected';
376 // Set server as connected
3770 _server.connected = true;
378 // Save document returned so we can query it
3790 _server.isMasterDoc = reply.documents[0];
380
3810 if(self.emitOpen) {
3820 _server._emitAcrossAllDbInstances(_server, eventReceiver, "open", null, returnIsMasterResults ? reply : null, null);
3830 self.emitOpen = false;
384 } else {
3850 _server._emitAcrossAllDbInstances(_server, eventReceiver, "reconnect", null, returnIsMasterResults ? reply : null, null);
386 }
387
388 // Set server capabilities
3890 server.serverCapabilities = new ServerCapabilities(_server.isMasterDoc);
390
391 // If we have it set to returnIsMasterResults
3920 if(returnIsMasterResults) {
3930 internalCallback(null, reply, _server);
394 } else {
3950 internalCallback(null, dbInstance, _server);
396 }
397 }
398 };
399
400 // Let's us override the main connect callback
4011 var connectHandler = options.connectHandler == null ? connectCallback(server) : options.connectHandler;
402
403 // Set up on connect method
4041 connectionPool.on("poolReady", function() {
405 // Create db command and Add the callback to the list of callbacks by the request id (mapping outgoing messages to correct callbacks)
4060 var db_command = DbCommand.NcreateIsMasterCommand(dbInstance, dbInstance.databaseName);
407 // Check out a reader from the pool
4080 var connection = connectionPool.checkoutConnection();
409 // Register handler for messages
4100 server._registerHandler(db_command, false, connection, connectHandler);
411 // Write the command out
4120 connection.write(db_command);
413 })
414
415 // Set up item connection
4161 connectionPool.on("message", function(message) {
417 // Attempt to parse the message
4180 try {
419 // Create a new mongo reply
4200 var mongoReply = new MongoReply()
421 // Parse the header
4220 mongoReply.parseHeader(message, connectionPool.bson)
423
424 // If message size is not the same as the buffer size
425 // something went terribly wrong somewhere
4260 if(mongoReply.messageLength != message.length) {
427 // Emit the error
4280 if(eventReceiver.listeners("error") && eventReceiver.listeners("error").length > 0) eventReceiver.emit("error", new Error("bson length is different from message length"), server);
429 // Remove all listeners
4300 server.removeAllListeners();
431 } else {
4320 var startDate = new Date().getTime();
433
434 // Callback instance
4350 var callbackInfo = server._findHandler(mongoReply.responseTo.toString());
436
437 // The command executed another request, log the handler again under that request id
4380 if(mongoReply.requestId > 0 && mongoReply.cursorId.toString() != "0"
439 && callbackInfo && callbackInfo.info && callbackInfo.info.exhaust) {
4400 server._reRegisterHandler(mongoReply.requestId, callbackInfo);
441 }
442 // Parse the body
4430 mongoReply.parseBody(message, connectionPool.bson, callbackInfo.info.raw, function(err) {
4440 if(err != null) {
445 // If pool connection is already closed
4460 if(server._serverState === 'disconnected') return;
447 // Set server state to disconnected
4480 server._serverState = 'disconnected';
449 // Remove all listeners and close the connection pool
4500 server.removeAllListeners();
4510 connectionPool.stop(true);
452
453 // If we have a callback return the error
4540 if(typeof callback === 'function') {
455 // ensure no callbacks get called twice
4560 var internalCallback = callback;
4570 callback = null;
458 // Perform callback
4590 internalCallback(err, null, server);
4600 } else if(server.isSetMember()) {
4610 if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", utils.toError(err), server);
462 } else {
4630 if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", utils.toError(err), server);
464 }
465
466 // If we are a single server connection fire errors correctly
4670 if(!server.isSetMember()) {
468 // Fire all callback errors
4690 server.__executeAllCallbacksWithError(err);
470 // Emit error
4710 server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true);
472 }
473 // Short cut
4740 return;
475 }
476
477 // Let's record the stats info if it's enabled
4780 if(server.recordQueryStats == true && server._state['runtimeStats'] != null
479 && server._state.runtimeStats['queryStats'] instanceof RunningStats) {
480 // Add data point to the running statistics object
4810 server._state.runtimeStats.queryStats.push(new Date().getTime() - callbackInfo.info.start);
482 }
483
484 // Dispatch the call
4850 server._callHandler(mongoReply.responseTo, mongoReply, null);
486
487 // If we have an error about the server not being master or primary
4880 if((mongoReply.responseFlag & (1 << 1)) != 0
489 && mongoReply.documents[0].code
490 && mongoReply.documents[0].code == 13436) {
4910 server.close();
492 }
493 });
494 }
495 } catch (err) {
496 // Throw error in next tick
4970 processor(function() {
4980 throw err;
499 })
500 }
501 });
502
503 // Handle timeout
5041 connectionPool.on("timeout", function(err) {
505 // If pool connection is already closed
5060 if(server._serverState === 'disconnected'
5070 || server._serverState === 'destroyed') return;
508 // Set server state to disconnected
5090 server._serverState = 'disconnected';
510 // If we have a callback return the error
5110 if(typeof callback === 'function') {
512 // ensure no callbacks get called twice
5130 var internalCallback = callback;
5140 callback = null;
515 // Perform callback
5160 internalCallback(err, null, server);
5170 } else if(server.isSetMember()) {
5180 if(server.listeners("timeout") && server.listeners("timeout").length > 0) server.emit("timeout", err, server);
519 } else {
5200 if(eventReceiver.listeners("timeout") && eventReceiver.listeners("timeout").length > 0) eventReceiver.emit("timeout", err, server);
521 }
522
523 // If we are a single server connection fire errors correctly
5240 if(!server.isSetMember()) {
525 // Fire all callback errors
5260 server.__executeAllCallbacksWithError(err);
527 // Emit error
5280 server._emitAcrossAllDbInstances(server, eventReceiver, "timeout", err, server, true);
529 }
530
531 // If we have autoConnect enabled let's fire up an attempt to reconnect
5320 if(server.isAutoReconnect()
533 && !server.isSetMember()
534 && (server._serverState != 'destroyed')
535 && !server._reconnectInProgreess) {
536 // Set the number of retries
5370 server._reconnect_retries = server.db.numberOfRetries;
538 // Attempt reconnect
5390 server._reconnectInProgreess = true;
5400 setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds);
541 }
542 });
543
544 // Handle errors
5451 connectionPool.on("error", function(message, connection, error_options) {
546 // If pool connection is already closed
5470 if(server._serverState === 'disconnected'
5480 || server._serverState === 'destroyed') return;
549
550 // Set server state to disconnected
5510 server._serverState = 'disconnected';
552 // Error message
5530 var error_message = new Error(message && message.err ? message.err : message);
554 // Error message coming from ssl
5550 if(error_options && error_options.ssl) error_message.ssl = true;
556
557 // If we have a callback return the error
5580 if(typeof callback === 'function') {
559 // ensure no callbacks get called twice
5600 var internalCallback = callback;
5610 callback = null;
562 // Perform callback
5630 internalCallback(error_message, null, server);
5640 } else if(server.isSetMember()) {
5650 if(server.listeners("error") && server.listeners("error").length > 0) server.emit("error", error_message, server);
566 } else {
5670 if(eventReceiver.listeners("error") && eventReceiver.listeners("error").length > 0) eventReceiver.emit("error", error_message, server);
568 }
569
570 // If we are a single server connection fire errors correctly
5710 if(!server.isSetMember()) {
572 // Fire all callback errors
5730 server.__executeAllCallbacksWithError(error_message);
574 // Emit error
5750 server._emitAcrossAllDbInstances(server, eventReceiver, "error", error_message, server, true);
576 }
577
578 // If we have autoConnect enabled let's fire up an attempt to reconnect
5790 if(server.isAutoReconnect()
580 && !server.isSetMember()
581 && (server._serverState != 'destroyed')
582 && !server._reconnectInProgreess) {
583
584 // Set the number of retries
5850 server._reconnect_retries = server.db.numberOfRetries;
586 // Attempt reconnect
5870 server._reconnectInProgreess = true;
5880 setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds);
589 }
590 });
591
592 // Handle close events
5931 connectionPool.on("close", function() {
594 // If pool connection is already closed
5950 if(server._serverState === 'disconnected'
5960 || server._serverState === 'destroyed') return;
597 // Set server state to disconnected
5980 server._serverState = 'disconnected';
599 // If we have a callback return the error
6000 if(typeof callback == 'function') {
601 // ensure no callbacks get called twice
6020 var internalCallback = callback;
6030 callback = null;
604 // Perform callback
6050 internalCallback(new Error("connection closed"), null, server);
6060 } else if(server.isSetMember()) {
6070 if(server.listeners("close") && server.listeners("close").length > 0) server.emit("close", new Error("connection closed"), server);
608 } else {
6090 if(eventReceiver.listeners("close") && eventReceiver.listeners("close").length > 0) eventReceiver.emit("close", new Error("connection closed"), server);
610 }
611
612 // If we are a single server connection fire errors correctly
6130 if(!server.isSetMember()) {
614 // Fire all callback errors
6150 server.__executeAllCallbacksWithError(new Error("connection closed"));
616 // Emit error
6170 server._emitAcrossAllDbInstances(server, eventReceiver, "close", server, null, true);
618 }
619
620 // If we have autoConnect enabled let's fire up an attempt to reconnect
6210 if(server.isAutoReconnect()
622 && !server.isSetMember()
623 && (server._serverState != 'destroyed')
624 && !server._reconnectInProgreess) {
625
626 // Set the number of retries
6270 server._reconnect_retries = server.db.numberOfRetries;
628 // Attempt reconnect
6290 server._reconnectInProgreess = true;
6300 setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds);
631 }
632 });
633
634 /**
635 * @ignore
636 */
6371 var __attemptReconnect = function(server) {
6380 return function() {
639 // Attempt reconnect
6400 server.connect(server.db, server.options, function(err, result) {
6410 server._reconnect_retries = server._reconnect_retries - 1;
642
6430 if(err) {
644 // Retry
6450 if(server._reconnect_retries == 0 || server._serverState == 'destroyed') {
6460 server._serverState = 'connected';
6470 server._reconnectInProgreess = false
648 // Fire all callback errors
6490 return server.__executeAllCallbacksWithError(new Error("failed to reconnect to server"));
650 } else {
6510 return setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds);
652 }
653 } else {
654 // Set as authenticating (isConnected will be false)
6550 server._serverState = 'authenticating';
656 // Apply any auths, we don't try to catch any errors here
657 // as there are nowhere to simply propagate them to
6580 self._apply_auths(server.db, function(err, result) {
6590 server._serverState = 'connected';
6600 server._reconnectInProgreess = false;
6610 server._commandsStore.execute_queries();
6620 server._commandsStore.execute_writes();
663 });
664 }
665 });
666 }
667 }
668
669 // If we have a parser error we are in an unknown state, close everything and emit
670 // error
6711 connectionPool.on("parseError", function(err) {
672 // If pool connection is already closed
6730 if(server._serverState === 'disconnected'
6740 || server._serverState === 'destroyed') return;
675 // Set server state to disconnected
6760 server._serverState = 'disconnected';
677 // If we have a callback return the error
6780 if(typeof callback === 'function') {
679 // ensure no callbacks get called twice
6800 var internalCallback = callback;
6810 callback = null;
682 // Perform callback
6830 internalCallback(utils.toError(err), null, server);
6840 } else if(server.isSetMember()) {
6850 if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", utils.toError(err), server);
686 } else {
6870 if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", utils.toError(err), server);
688 }
689
690 // If we are a single server connection fire errors correctly
6910 if(!server.isSetMember()) {
692 // Fire all callback errors
6930 server.__executeAllCallbacksWithError(utils.toError(err));
694 // Emit error
6950 server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true);
696 }
697 });
698
699 // Boot up connection poole, pass in a locator of callbacks
7001 connectionPool.start();
701}
702
703/**
704 * @ignore
705 */
7061Server.prototype.allRawConnections = function() {
7070 return this.connectionPool != null ? this.connectionPool.getAllConnections() : [];
708}
709
710/**
711 * Check if a writer can be provided
712 * @ignore
713 */
7141var canCheckoutWriter = function(self, read) {
715 // We cannot write to an arbiter or secondary server
7160 if(self.isMasterDoc && self.isMasterDoc['arbiterOnly'] == true) {
7170 return new Error("Cannot write to an arbiter");
7180 } if(self.isMasterDoc && self.isMasterDoc['secondary'] == true) {
7190 return new Error("Cannot write to a secondary");
7200 } else if(read == true && self._readPreference == ReadPreference.SECONDARY && self.isMasterDoc && self.isMasterDoc['ismaster'] == true) {
7210 return new Error("Cannot read from primary when secondary only specified");
7220 } else if(!self.isMasterDoc) {
7230 return new Error("Cannot determine state of server");
724 }
725
726 // Return no error
7270 return null;
728}
729
730/**
731 * @ignore
732 */
7331Server.prototype.checkoutWriter = function(read) {
7340 if(read == true) return this.connectionPool.checkoutConnection();
735 // Check if are allowed to do a checkout (if we try to use an arbiter f.ex)
7360 var result = canCheckoutWriter(this, read);
737 // If the result is null check out a writer
7380 if(result == null && this.connectionPool != null) {
7390 var connection = this.connectionPool.checkoutConnection();
740 // Add server capabilities to the connection
7410 if(connection)
7420 connection.serverCapabilities = this.serverCapabilities;
7430 return connection;
7440 } else if(result == null) {
7450 return null;
746 } else {
7470 return result;
748 }
749}
750
751/**
752 * Check if a reader can be provided
753 * @ignore
754 */
7551var canCheckoutReader = function(self) {
756 // We cannot write to an arbiter or secondary server
7570 if(self.isMasterDoc && self.isMasterDoc['arbiterOnly'] == true) {
7580 return new Error("Cannot write to an arbiter");
7590 } else if(self._readPreference != null) {
760 // If the read preference is Primary and the instance is not a master return an error
7610 if((self._readPreference == ReadPreference.PRIMARY) && self.isMasterDoc && self.isMasterDoc['ismaster'] != true) {
7620 return new Error("Read preference is Server.PRIMARY and server is not master");
7630 } else if(self._readPreference == ReadPreference.SECONDARY && self.isMasterDoc && self.isMasterDoc['ismaster'] == true) {
7640 return new Error("Cannot read from primary when secondary only specified");
765 }
7660 } else if(!self.isMasterDoc) {
7670 return new Error("Cannot determine state of server");
768 }
769
770 // Return no error
7710 return null;
772}
773
774/**
775 * @ignore
776 */
7771Server.prototype.checkoutReader = function(read) {
778 // Check if are allowed to do a checkout (if we try to use an arbiter f.ex)
7790 var result = canCheckoutReader(this);
780 // If the result is null check out a writer
7810 if(result == null && this.connectionPool != null) {
7820 var connection = this.connectionPool.checkoutConnection();
783 // Add server capabilities to the connection
7840 if(connection)
7850 connection.serverCapabilities = this.serverCapabilities;
7860 return connection;
7870 } else if(result == null) {
7880 return null;
789 } else {
7900 return result;
791 }
792}
793
794/**
795 * @ignore
796 */
7971Server.prototype.enableRecordQueryStats = function(enable) {
7980 this.recordQueryStats = enable;
799}
800
801/**
802 * Internal statistics object used for calculating average and standard devitation on
803 * running queries
804 * @ignore
805 */
8061var RunningStats = function() {
8071 var self = this;
8081 this.m_n = 0;
8091 this.m_oldM = 0.0;
8101 this.m_oldS = 0.0;
8111 this.m_newM = 0.0;
8121 this.m_newS = 0.0;
813
814 // Define getters
8151 Object.defineProperty(this, "numDataValues", { enumerable: true
8160 , get: function () { return this.m_n; }
817 });
818
8191 Object.defineProperty(this, "mean", { enumerable: true
8200 , get: function () { return (this.m_n > 0) ? this.m_newM : 0.0; }
821 });
822
8231 Object.defineProperty(this, "variance", { enumerable: true
8240 , get: function () { return ((this.m_n > 1) ? this.m_newS/(this.m_n - 1) : 0.0); }
825 });
826
8271 Object.defineProperty(this, "standardDeviation", { enumerable: true
8280 , get: function () { return Math.sqrt(this.variance); }
829 });
830
8311 Object.defineProperty(this, "sScore", { enumerable: true
832 , get: function () {
8330 var bottom = this.mean + this.standardDeviation;
8340 if(bottom == 0) return 0;
8350 return ((2 * this.mean * this.standardDeviation)/(bottom));
836 }
837 });
838}
839
840/**
841 * @ignore
842 */
8431RunningStats.prototype.push = function(x) {
844 // Update the number of samples
8450 this.m_n = this.m_n + 1;
846 // See Knuth TAOCP vol 2, 3rd edition, page 232
8470 if(this.m_n == 1) {
8480 this.m_oldM = this.m_newM = x;
8490 this.m_oldS = 0.0;
850 } else {
8510 this.m_newM = this.m_oldM + (x - this.m_oldM) / this.m_n;
8520 this.m_newS = this.m_oldS + (x - this.m_oldM) * (x - this.m_newM);
853
854 // set up for next iteration
8550 this.m_oldM = this.m_newM;
8560 this.m_oldS = this.m_newS;
857 }
858}
859
860/**
861 * @ignore
862 */
8631Object.defineProperty(Server.prototype, "autoReconnect", { enumerable: true
864 , get: function () {
8650 return this.options['auto_reconnect'] == null ? false : this.options['auto_reconnect'];
866 }
867});
868
869/**
870 * @ignore
871 */
8721Object.defineProperty(Server.prototype, "connection", { enumerable: true
873 , get: function () {
8740 return this.internalConnection;
875 }
876 , set: function(connection) {
8770 this.internalConnection = connection;
878 }
879});
880
881/**
882 * @ignore
883 */
8841Object.defineProperty(Server.prototype, "master", { enumerable: true
885 , get: function () {
8860 return this.internalMaster;
887 }
888 , set: function(value) {
8890 this.internalMaster = value;
890 }
891});
892
893/**
894 * @ignore
895 */
8961Object.defineProperty(Server.prototype, "primary", { enumerable: true
897 , get: function () {
8980 return this;
899 }
900});
901
902/**
903 * Getter for query Stats
904 * @ignore
905 */
9061Object.defineProperty(Server.prototype, "queryStats", { enumerable: true
907 , get: function () {
9080 return this._state.runtimeStats.queryStats;
909 }
910});
911
912/**
913 * @ignore
914 */
9151Object.defineProperty(Server.prototype, "runtimeStats", { enumerable: true
916 , get: function () {
9170 return this._state.runtimeStats;
918 }
919});
920
921/**
922 * Get Read Preference method
923 * @ignore
924 */
9251Object.defineProperty(Server.prototype, "readPreference", { enumerable: true
926 , get: function () {
9270 if(this._readPreference == null && this.readSecondary) {
9280 return Server.READ_SECONDARY;
9290 } else if(this._readPreference == null && !this.readSecondary) {
9300 return Server.READ_PRIMARY;
931 } else {
9320 return this._readPreference;
933 }
934 }
935});
936
937/**
938 * @ignore
939 */
9401exports.Server = Server;
941

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server_capabilities.js

10%
28
3
25
LineHitsSource
11var ServerCapabilities = function(isMasterResult) {
2 // Capabilities
30 var aggregationCursor = false;
40 var writeCommands = false;
50 var textSearch = false;
60 var authCommands = false;
70 var maxNumberOfDocsInBatch = 1000;
8
90 if(isMasterResult.minWireVersion >= 0) {
100 textSearch = true;
11 }
12
130 if(isMasterResult.maxWireVersion >= 1) {
140 aggregationCursor = true;
150 authCommands = true;
16 }
17
180 if(isMasterResult.maxWireVersion >= 2) {
190 writeCommands = true;
20 }
21
22 // If no min or max wire version set to 0
230 if(isMasterResult.minWireVersion == null) {
240 isMasterResult.minWireVersion = 0;
25 }
26
270 if(isMasterResult.maxWireVersion == null) {
280 isMasterResult.maxWireVersion = 0;
29 }
30
31 // Map up read only parameters
320 setup_get_property(this, "hasAggregationCursor", aggregationCursor);
330 setup_get_property(this, "hasWriteCommands", writeCommands);
340 setup_get_property(this, "hasTextSearch", textSearch);
350 setup_get_property(this, "hasAuthCommands", authCommands);
360 setup_get_property(this, "minWireVersion", isMasterResult.minWireVersion);
370 setup_get_property(this, "maxWireVersion", isMasterResult.maxWireVersion);
380 setup_get_property(this, "maxNumberOfDocsInBatch", maxNumberOfDocsInBatch);
39}
40
411var setup_get_property = function(object, name, value) {
420 Object.defineProperty(object, name, {
43 enumerable: true
440 , get: function () { return value; }
45 });
46}
47
481exports.ServerCapabilities = ServerCapabilities;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/url_parser.js

1%
141
2
139
LineHitsSource
11var fs = require('fs'),
2 ReadPreference = require('./read_preference').ReadPreference;
3
41exports.parse = function(url, options) {
5 // Ensure we have a default options object if none set
60 options = options || {};
7 // Variables
80 var connection_part = '';
90 var auth_part = '';
100 var query_string_part = '';
110 var dbName = 'admin';
12
13 // Must start with mongodb
140 if(url.indexOf("mongodb://") != 0)
150 throw Error("URL must be in the format mongodb://user:pass@host:port/dbname");
16 // If we have a ? mark cut the query elements off
170 if(url.indexOf("?") != -1) {
180 query_string_part = url.substr(url.indexOf("?") + 1);
190 connection_part = url.substring("mongodb://".length, url.indexOf("?"))
20 } else {
210 connection_part = url.substring("mongodb://".length);
22 }
23
24 // Check if we have auth params
250 if(connection_part.indexOf("@") != -1) {
260 auth_part = connection_part.split("@")[0];
270 connection_part = connection_part.split("@")[1];
28 }
29
30 // Check if the connection string has a db
310 if(connection_part.indexOf(".sock") != -1) {
320 if(connection_part.indexOf(".sock/") != -1) {
330 dbName = connection_part.split(".sock/")[1];
340 connection_part = connection_part.split("/", connection_part.indexOf(".sock") + ".sock".length);
35 }
360 } else if(connection_part.indexOf("/") != -1) {
370 dbName = connection_part.split("/")[1];
380 connection_part = connection_part.split("/")[0];
39 }
40
41 // Result object
420 var object = {};
43
44 // Pick apart the authentication part of the string
450 var authPart = auth_part || '';
460 var auth = authPart.split(':', 2);
470 if(options['uri_decode_auth']){
480 auth[0] = decodeURIComponent(auth[0]);
490 if(auth[1]){
500 auth[1] = decodeURIComponent(auth[1]);
51 }
52 }
53
54 // Add auth to final object if we have 2 elements
550 if(auth.length == 2) object.auth = {user: auth[0], password: auth[1]};
56
57 // Variables used for temporary storage
580 var hostPart;
590 var urlOptions;
600 var servers;
610 var serverOptions = {socketOptions: {}};
620 var dbOptions = {read_preference_tags: []};
630 var replSetServersOptions = {socketOptions: {}};
64 // Add server options to final object
650 object.server_options = serverOptions;
660 object.db_options = dbOptions;
670 object.rs_options = replSetServersOptions;
680 object.mongos_options = {};
69
70 // Let's check if we are using a domain socket
710 if(url.match(/\.sock/)) {
72 // Split out the socket part
730 var domainSocket = url.substring(
74 url.indexOf("mongodb://") + "mongodb://".length
75 , url.lastIndexOf(".sock") + ".sock".length);
76 // Clean out any auth stuff if any
770 if(domainSocket.indexOf("@") != -1) domainSocket = domainSocket.split("@")[1];
780 servers = [{domain_socket: domainSocket}];
79 } else {
80 // Split up the db
810 hostPart = connection_part;
82 // Parse all server results
830 servers = hostPart.split(',').map(function(h) {
840 var hostPort = h.split(':', 2);
850 var _host = hostPort[0] || 'localhost';
860 var _port = hostPort[1] != null ? parseInt(hostPort[1], 10) : 27017;
87 // Check for localhost?safe=true style case
880 if(_host.indexOf("?") != -1) _host = _host.split(/\?/)[0];
89
90 // Return the mapped object
910 return {host: _host, port: _port};
92 });
93 }
94
95 // Get the db name
960 object.dbName = dbName || 'admin';
97 // Split up all the options
980 urlOptions = (query_string_part || '').split(/[&;]/);
99 // Ugh, we have to figure out which options go to which constructor manually.
1000 urlOptions.forEach(function(opt) {
1010 if(!opt) return;
1020 var splitOpt = opt.split('='), name = splitOpt[0], value = splitOpt[1];
103 // Options implementations
1040 switch(name) {
105 case 'slaveOk':
106 case 'slave_ok':
1070 serverOptions.slave_ok = (value == 'true');
1080 dbOptions.slaveOk = (value == 'true');
1090 break;
110 case 'maxPoolSize':
111 case 'poolSize':
1120 serverOptions.poolSize = parseInt(value, 10);
1130 replSetServersOptions.poolSize = parseInt(value, 10);
1140 break;
115 case 'autoReconnect':
116 case 'auto_reconnect':
1170 serverOptions.auto_reconnect = (value == 'true');
1180 break;
119 case 'minPoolSize':
1200 throw new Error("minPoolSize not supported");
121 case 'maxIdleTimeMS':
1220 throw new Error("maxIdleTimeMS not supported");
123 case 'waitQueueMultiple':
1240 throw new Error("waitQueueMultiple not supported");
125 case 'waitQueueTimeoutMS':
1260 throw new Error("waitQueueTimeoutMS not supported");
127 case 'uuidRepresentation':
1280 throw new Error("uuidRepresentation not supported");
129 case 'ssl':
1300 if(value == 'prefer') {
1310 serverOptions.ssl = value;
1320 replSetServersOptions.ssl = value;
1330 break;
134 }
1350 serverOptions.ssl = (value == 'true');
1360 replSetServersOptions.ssl = (value == 'true');
1370 break;
138 case 'replicaSet':
139 case 'rs_name':
1400 replSetServersOptions.rs_name = value;
1410 break;
142 case 'reconnectWait':
1430 replSetServersOptions.reconnectWait = parseInt(value, 10);
1440 break;
145 case 'retries':
1460 replSetServersOptions.retries = parseInt(value, 10);
1470 break;
148 case 'readSecondary':
149 case 'read_secondary':
1500 replSetServersOptions.read_secondary = (value == 'true');
1510 break;
152 case 'fsync':
1530 dbOptions.fsync = (value == 'true');
1540 break;
155 case 'journal':
1560 dbOptions.journal = (value == 'true');
1570 break;
158 case 'safe':
1590 dbOptions.safe = (value == 'true');
1600 break;
161 case 'nativeParser':
162 case 'native_parser':
1630 dbOptions.native_parser = (value == 'true');
1640 break;
165 case 'connectTimeoutMS':
1660 serverOptions.socketOptions.connectTimeoutMS = parseInt(value, 10);
1670 replSetServersOptions.socketOptions.connectTimeoutMS = parseInt(value, 10);
1680 break;
169 case 'socketTimeoutMS':
1700 serverOptions.socketOptions.socketTimeoutMS = parseInt(value, 10);
1710 replSetServersOptions.socketOptions.socketTimeoutMS = parseInt(value, 10);
1720 break;
173 case 'w':
1740 dbOptions.w = parseInt(value, 10);
1750 break;
176 case 'authSource':
1770 dbOptions.authSource = value;
1780 break;
179 case 'gssapiServiceName':
1800 dbOptions.gssapiServiceName = value;
1810 break;
182 case 'authMechanism':
1830 if(value == 'GSSAPI') {
184 // If no password provided decode only the principal
1850 if(object.auth == null) {
1860 var urlDecodeAuthPart = decodeURIComponent(authPart);
1870 if(urlDecodeAuthPart.indexOf("@") == -1) throw new Error("GSSAPI requires a provided principal");
1880 object.auth = {user: urlDecodeAuthPart, password: null};
189 } else {
1900 object.auth.user = decodeURIComponent(object.auth.user);
191 }
1920 } else if(value == 'MONGODB-X509') {
1930 object.auth = {user: decodeURIComponent(authPart)};
194 }
195
196 // Only support GSSAPI or MONGODB-CR for now
1970 if(value != 'GSSAPI'
198 && value != 'MONGODB-X509'
199 && value != 'MONGODB-CR'
200 && value != 'PLAIN')
2010 throw new Error("only GSSAPI, PLAIN, MONGODB-X509 or MONGODB-CR is supported by authMechanism");
202
203 // Authentication mechanism
2040 dbOptions.authMechanism = value;
2050 break;
206 case 'wtimeoutMS':
2070 dbOptions.wtimeoutMS = parseInt(value, 10);
2080 break;
209 case 'readPreference':
2100 if(!ReadPreference.isValid(value)) throw new Error("readPreference must be either primary/primaryPreferred/secondary/secondaryPreferred/nearest");
2110 dbOptions.read_preference = value;
2120 break;
213 case 'readPreferenceTags':
214 // Contains the tag object
2150 var tagObject = {};
2160 if(value == null || value == '') {
2170 dbOptions.read_preference_tags.push(tagObject);
2180 break;
219 }
220
221 // Split up the tags
2220 var tags = value.split(/\,/);
2230 for(var i = 0; i < tags.length; i++) {
2240 var parts = tags[i].trim().split(/\:/);
2250 tagObject[parts[0]] = parts[1];
226 }
227
228 // Set the preferences tags
2290 dbOptions.read_preference_tags.push(tagObject);
2300 break;
231 default:
2320 break;
233 }
234 });
235
236 // No tags: should be null (not [])
2370 if(dbOptions.read_preference_tags.length === 0) {
2380 dbOptions.read_preference_tags = null;
239 }
240
241 // Validate if there are an invalid write concern combinations
2420 if((dbOptions.w == -1 || dbOptions.w == 0) && (
243 dbOptions.journal == true
244 || dbOptions.fsync == true
2450 || dbOptions.safe == true)) throw new Error("w set to -1 or 0 cannot be combined with safe/w/journal/fsync")
246
247 // If no read preference set it to primary
2480 if(!dbOptions.read_preference) dbOptions.read_preference = 'primary';
249
250 // Add servers to result
2510 object.servers = servers;
252 // Returned parsed object
2530 return object;
254}
255

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursor.js

8%
394
32
362
LineHitsSource
11var QueryCommand = require('./commands/query_command').QueryCommand,
2 GetMoreCommand = require('./commands/get_more_command').GetMoreCommand,
3 KillCursorCommand = require('./commands/kill_cursor_command').KillCursorCommand,
4 Long = require('bson').Long,
5 ReadPreference = require('./connection/read_preference').ReadPreference,
6 CursorStream = require('./cursorstream'),
7 timers = require('timers'),
8 utils = require('./utils');
9
10// Set processor, setImmediate if 0.10 otherwise nextTick
111var processor = require('./utils').processor();
12
13/**
14 * Constructor for a cursor object that handles all the operations on query result
15 * using find. This cursor object is unidirectional and cannot traverse backwards. Clients should not be creating a cursor directly,
16 * but use find to acquire a cursor. (INTERNAL TYPE)
17 *
18 * Options
19 * - **skip** {Number} skip number of documents to skip.
20 * - **limit** {Number}, limit the number of results to return. -1 has a special meaning and is used by Db.eval. A value of 1 will also be treated as if it were -1.
21 * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc.
22 * - **hint** {Object}, hint force the query to use a specific index.
23 * - **explain** {Boolean}, explain return the explaination of the query.
24 * - **snapshot** {Boolean}, snapshot Snapshot mode assures no duplicates are returned.
25 * - **timeout** {Boolean}, timeout allow the query to timeout.
26 * - **tailable** {Boolean}, tailable allow the cursor to be tailable.
27 * - **awaitdata** {Boolean}, awaitdata allow the cursor to wait for data, only applicable for tailable cursor.
28 * - **oplogReplay** {Boolean}, sets an internal flag, only applicable for tailable cursor.
29 * - **batchSize** {Number}, batchSize the number of the subset of results to request the database to return for every request. This should initially be greater than 1 otherwise the database will automatically close the cursor. The batch size can be set to 1 with cursorInstance.batchSize after performing the initial query to the database.
30 * - **raw** {Boolean}, raw return all query documents as raw buffers (default false).
31 * - **read** {Boolean}, read specify override of read from source (primary/secondary).
32 * - **returnKey** {Boolean}, returnKey only return the index key.
33 * - **maxScan** {Number}, maxScan limit the number of items to scan.
34 * - **min** {Number}, min set index bounds.
35 * - **max** {Number}, max set index bounds.
36 * - **maxTimeMS** {Number}, number of miliseconds to wait before aborting the query.
37 * - **showDiskLoc** {Boolean}, showDiskLoc show disk location of results.
38 * - **comment** {String}, comment you can put a $comment field on a query to make looking in the profiler logs simpler.
39 * - **numberOfRetries** {Number}, numberOfRetries if using awaidata specifies the number of times to retry on timeout.
40 * - **dbName** {String}, dbName override the default dbName.
41 * - **tailableRetryInterval** {Number}, tailableRetryInterval specify the miliseconds between getMores on tailable cursor.
42 * - **exhaust** {Boolean}, exhaust have the server send all the documents at once as getMore packets.
43 * - **partial** {Boolean}, partial have the sharded system return a partial result from mongos.
44 *
45 * @class Represents a Cursor.
46 * @param {Db} db the database object to work with.
47 * @param {Collection} collection the collection to query.
48 * @param {Object} selector the query selector.
49 * @param {Object} fields an object containing what fields to include or exclude from objects returned.
50 * @param {Object} [options] additional options for the collection.
51*/
521function Cursor(db, collection, selector, fields, options) {
530 this.db = db;
540 this.collection = collection;
550 this.selector = selector;
560 this.fields = fields;
570 options = !options ? {} : options;
58
590 this.skipValue = options.skip == null ? 0 : options.skip;
600 this.limitValue = options.limit == null ? 0 : options.limit;
610 this.sortValue = options.sort;
620 this.hint = options.hint;
630 this.explainValue = options.explain;
640 this.snapshot = options.snapshot;
650 this.timeout = options.timeout == null ? true : options.timeout;
660 this.tailable = options.tailable;
670 this.awaitdata = options.awaitdata;
680 this.oplogReplay = options.oplogReplay;
690 this.numberOfRetries = options.numberOfRetries == null ? 5 : options.numberOfRetries;
700 this.currentNumberOfRetries = this.numberOfRetries;
710 this.batchSizeValue = options.batchSize == null ? 0 : options.batchSize;
720 this.raw = options.raw == null ? false : options.raw;
730 this.read = options.read == null ? ReadPreference.PRIMARY : options.read;
740 this.returnKey = options.returnKey;
750 this.maxScan = options.maxScan;
760 this.min = options.min;
770 this.max = options.max;
780 this.showDiskLoc = options.showDiskLoc;
790 this.comment = options.comment;
800 this.tailableRetryInterval = options.tailableRetryInterval || 100;
810 this.exhaust = options.exhaust || false;
820 this.partial = options.partial || false;
830 this.slaveOk = options.slaveOk || false;
840 this.maxTimeMSValue = options.maxTimeMS;
85
860 this.totalNumberOfRecords = 0;
870 this.items = [];
880 this.cursorId = Long.fromInt(0);
89
90 // This name
910 this.dbName = options.dbName;
92
93 // State variables for the cursor
940 this.state = Cursor.INIT;
95 // Keep track of the current query run
960 this.queryRun = false;
970 this.getMoreTimer = false;
98
99 // If we are using a specific db execute against it
1000 if(this.dbName != null) {
1010 this.collectionName = this.dbName + "." + this.collection.collectionName;
102 } else {
1030 this.collectionName = (this.db.databaseName ? this.db.databaseName + "." : '') + this.collection.collectionName;
104 }
105};
106
107/**
108 * Resets this cursor to its initial state. All settings like the query string,
109 * tailable, batchSizeValue, skipValue and limits are preserved.
110 *
111 * @return {Cursor} returns itself with rewind applied.
112 * @api public
113 */
1141Cursor.prototype.rewind = function() {
1150 var self = this;
116
1170 if (self.state != Cursor.INIT) {
1180 if (self.state != Cursor.CLOSED) {
1190 self.close(function() {});
120 }
121
1220 self.numberOfReturned = 0;
1230 self.totalNumberOfRecords = 0;
1240 self.items = [];
1250 self.cursorId = Long.fromInt(0);
1260 self.state = Cursor.INIT;
1270 self.queryRun = false;
128 }
129
1300 return self;
131};
132
133
134/**
135 * Returns an array of documents. The caller is responsible for making sure that there
136 * is enough memory to store the results. Note that the array only contain partial
137 * results when this cursor had been previouly accessed. In that case,
138 * cursor.rewind() can be used to reset the cursor.
139 *
140 * @param {Function} callback This will be called after executing this method successfully. The first parameter will contain the Error object if an error occured, or null otherwise. The second parameter will contain an array of BSON deserialized objects as a result of the query.
141 * @return {null}
142 * @api public
143 */
1441Cursor.prototype.toArray = function(callback) {
1450 var self = this;
146
1470 if(!callback) {
1480 throw new Error('callback is mandatory');
149 }
150
1510 if(this.tailable) {
1520 callback(new Error("Tailable cursor cannot be converted to array"), null);
1530 } else if(this.state != Cursor.CLOSED) {
154 // return toArrayExhaust(self, callback);
155 // If we are using exhaust we can't use the quick fire method
1560 if(self.exhaust) return toArrayExhaust(self, callback);
157 // Quick fire using trampoline to avoid nextTick
1580 self.nextObject({noReturn: true}, function(err, result) {
1590 if(err) return callback(utils.toError(err), null);
1600 if(self.cursorId.toString() == "0") {
1610 self.state = Cursor.CLOSED;
1620 return callback(null, self.items);
163 }
164
165 // Let's issue getMores until we have no more records waiting
1660 getAllByGetMore(self, function(err, done) {
1670 self.state = Cursor.CLOSED;
1680 if(err) return callback(utils.toError(err), null);
169 // Let's release the internal list
1700 var items = self.items;
1710 self.items = null;
172 // Return all the items
1730 callback(null, items);
174 });
175 })
176
177 } else {
1780 callback(new Error("Cursor is closed"), null);
179 }
180}
181
1821var toArrayExhaust = function(self, callback) {
1830 var items = [];
184
1850 self.each(function(err, item) {
1860 if(err != null) {
1870 return callback(utils.toError(err), null);
188 }
189
1900 if(item != null && Array.isArray(items)) {
1910 items.push(item);
192 } else {
1930 var resultItems = items;
1940 items = null;
1950 self.items = [];
1960 callback(null, resultItems);
197 }
198 });
199}
200
2011var getAllByGetMore = function(self, callback) {
2020 getMore(self, {noReturn: true}, function(err, result) {
2030 if(err) return callback(utils.toError(err));
2040 if(result == null) return callback(null, null);
2050 if(self.cursorId.toString() == "0") return callback(null, null);
2060 getAllByGetMore(self, callback);
207 })
208};
209
210/**
211 * Iterates over all the documents for this cursor. As with **{cursor.toArray}**,
212 * not all of the elements will be iterated if this cursor had been previouly accessed.
213 * In that case, **{cursor.rewind}** can be used to reset the cursor. However, unlike
214 * **{cursor.toArray}**, the cursor will only hold a maximum of batch size elements
215 * at any given time if batch size is specified. Otherwise, the caller is responsible
216 * for making sure that the entire result can fit the memory.
217 *
218 * @param {Function} callback this will be called for while iterating every document of the query result. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the document.
219 * @return {null}
220 * @api public
221 */
2221Cursor.prototype.each = function(callback) {
2230 var self = this;
2240 var fn;
225
2260 if (!callback) {
2270 throw new Error('callback is mandatory');
228 }
229
2300 if(this.state != Cursor.CLOSED) {
231 // If we are using exhaust we can't use the quick fire method
2320 if(self.exhaust) return eachExhaust(self, callback);
233 // Quick fire using trampoline to avoid nextTick
2340 if(this.items.length > 0) {
235 // Trampoline all the entries
2360 while(fn = loop(self, callback)) fn(self, callback);
237 // Call each again
2380 self.each(callback);
239 } else {
2400 self.nextObject(function(err, item) {
241
2420 if(err) {
2430 self.state = Cursor.CLOSED;
2440 return callback(utils.toError(err), item);
245 }
246
2470 if(item == null) return callback(null, null);
2480 callback(null, item);
2490 self.each(callback);
250 })
251 }
252 } else {
2530 callback(new Error("Cursor is closed"), null);
254 }
255};
256
257// Special for exhaust command as we don't initiate the actual result sets
258// the server just sends them as they arrive meaning we need to get the IO event
259// loop happen so we can receive more data from the socket or we return to early
260// after the first fetch and loose all the incoming getMore's automatically issued
261// from the server.
2621var eachExhaust = function(self, callback) {
263 //FIX: stack overflow (on deep callback) (cred: https://github.com/limp/node-mongodb-native/commit/27da7e4b2af02035847f262b29837a94bbbf6ce2)
2640 processor(function(){
265 // Fetch the next object until there is no more objects
2660 self.nextObject(function(err, item) {
2670 if(err != null) return callback(err, null);
2680 if(item != null) {
2690 callback(null, item);
2700 eachExhaust(self, callback);
271 } else {
272 // Close the cursor if done
2730 self.state = Cursor.CLOSED;
2740 callback(err, null);
275 }
276 });
277 });
278}
279
280// Trampoline emptying the number of retrieved items
281// without incurring a nextTick operation
2821var loop = function(self, callback) {
283 // No more items we are done
2840 if(self.items.length == 0) return;
285 // Get the next document
2860 var doc = self.items.shift();
287 // Callback
2880 callback(null, doc);
289 // Loop
2900 return loop;
291}
292
293/**
294 * Determines how many result the query for this cursor will return
295 *
296 * @param {Boolean} applySkipLimit if set to true will apply the skip and limits set on the cursor. Defaults to false.
297 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the number of results or null if an error occured.
298 * @return {null}
299 * @api public
300 */
3011Cursor.prototype.count = function(applySkipLimit, callback) {
3020 if(typeof applySkipLimit == 'function') {
3030 callback = applySkipLimit;
3040 applySkipLimit = false;
305 }
306
3070 var options = {};
3080 if(applySkipLimit) {
3090 if(typeof this.skipValue == 'number') options.skip = this.skipValue;
3100 if(typeof this.limitValue == 'number') options.limit = this.limitValue;
311 }
312
313 // If maxTimeMS set
3140 if(typeof this.maxTimeMSValue == 'number') options.maxTimeMS = this.maxTimeMSValue;
315
316 // Call count command
3170 this.collection.count(this.selector, options, callback);
318};
319
320/**
321 * Sets the sort parameter of this cursor to the given value.
322 *
323 * This method has the following method signatures:
324 * (keyOrList, callback)
325 * (keyOrList, direction, callback)
326 *
327 * @param {String|Array|Object} keyOrList This can be a string or an array. If passed as a string, the string will be the field to sort. If passed an array, each element will represent a field to be sorted and should be an array that contains the format [string, direction].
328 * @param {String|Number} direction this determines how the results are sorted. "asc", "ascending" or 1 for asceding order while "desc", "desceding or -1 for descending order. Note that the strings are case insensitive.
329 * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
330 * @return {Cursor} an instance of this object.
331 * @api public
332 */
3331Cursor.prototype.sort = function(keyOrList, direction, callback) {
3340 callback = callback || function(){};
3350 if(typeof direction === "function") { callback = direction; direction = null; }
336
3370 if(this.tailable) {
3380 callback(new Error("Tailable cursor doesn't support sorting"), null);
3390 } else if(this.queryRun == true || this.state == Cursor.CLOSED) {
3400 callback(new Error("Cursor is closed"), null);
341 } else {
3420 var order = keyOrList;
343
3440 if(direction != null) {
3450 order = [[keyOrList, direction]];
346 }
347
3480 this.sortValue = order;
3490 callback(null, this);
350 }
3510 return this;
352};
353
354/**
355 * Sets the limit parameter of this cursor to the given value.
356 *
357 * @param {Number} limit the new limit.
358 * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
359 * @return {Cursor} an instance of this object.
360 * @api public
361 */
3621Cursor.prototype.limit = function(limit, callback) {
3630 if(this.tailable) {
3640 if(callback) {
3650 callback(new Error("Tailable cursor doesn't support limit"), null);
366 } else {
3670 throw new Error("Tailable cursor doesn't support limit");
368 }
3690 } else if(this.queryRun == true || this.state == Cursor.CLOSED) {
3700 if(callback) {
3710 callback(new Error("Cursor is closed"), null);
372 } else {
3730 throw new Error("Cursor is closed");
374 }
375 } else {
3760 if(limit != null && limit.constructor != Number) {
3770 if(callback) {
3780 callback(new Error("limit requires an integer"), null);
379 } else {
3800 throw new Error("limit requires an integer");
381 }
382 } else {
3830 this.limitValue = limit;
3840 if(callback) return callback(null, this);
385 }
386 }
387
3880 return this;
389};
390
391/**
392 * Specifies a time limit for a query operation. After the specified
393 * time is exceeded, the operation will be aborted and an error will be
394 * returned to the client. If maxTimeMS is null, no limit is applied.
395 *
396 * @param {Number} maxTimeMS the maxTimeMS for the query.
397 * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
398 * @return {Cursor} an instance of this object.
399 * @api public
400 */
4011Cursor.prototype.maxTimeMS = function(maxTimeMS, callback) {
4020 if(typeof maxTimeMS != 'number') {
4030 throw new Error("maxTimeMS must be a number");
404 }
405
406 // Save the maxTimeMS option
4070 this.maxTimeMSValue = maxTimeMS;
408 // Return the cursor for chaining
4090 return this;
410};
411
412/**
413 * Sets the read preference for the cursor
414 *
415 * @param {String} the read preference for the cursor, one of Server.READ_PRIMARY, Server.READ_SECONDARY, Server.READ_SECONDARY_ONLY
416 * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the read preference given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
417 * @return {Cursor} an instance of this object.
418 * @api public
419 */
4201Cursor.prototype.setReadPreference = function(readPreference, tags, callback) {
4210 if(typeof tags == 'function') callback = tags;
422
4230 var _mode = readPreference != null && typeof readPreference == 'object' ? readPreference.mode : readPreference;
424
4250 if(this.queryRun == true || this.state == Cursor.CLOSED) {
4260 if(callback == null) throw new Error("Cannot change read preference on executed query or closed cursor");
4270 callback(new Error("Cannot change read preference on executed query or closed cursor"));
4280 } else if(_mode != null && _mode != 'primary'
429 && _mode != 'secondaryOnly' && _mode != 'secondary'
430 && _mode != 'nearest' && _mode != 'primaryPreferred' && _mode != 'secondaryPreferred') {
4310 if(callback == null) throw new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported");
4320 callback(new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported"));
433 } else {
4340 this.read = readPreference;
4350 if(callback != null) callback(null, this);
436 }
437
4380 return this;
439}
440
441/**
442 * Sets the skip parameter of this cursor to the given value.
443 *
444 * @param {Number} skip the new skip value.
445 * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the skip value given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
446 * @return {Cursor} an instance of this object.
447 * @api public
448 */
4491Cursor.prototype.skip = function(skip, callback) {
4500 callback = callback || function(){};
451
4520 if(this.tailable) {
4530 callback(new Error("Tailable cursor doesn't support skip"), null);
4540 } else if(this.queryRun == true || this.state == Cursor.CLOSED) {
4550 callback(new Error("Cursor is closed"), null);
456 } else {
4570 if(skip != null && skip.constructor != Number) {
4580 callback(new Error("skip requires an integer"), null);
459 } else {
4600 this.skipValue = skip;
4610 callback(null, this);
462 }
463 }
464
4650 return this;
466};
467
468/**
469 * Sets the batch size parameter of this cursor to the given value.
470 *
471 * @param {Number} batchSize the new batch size.
472 * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the batchSize given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution.
473 * @return {Cursor} an instance of this object.
474 * @api public
475 */
4761Cursor.prototype.batchSize = function(batchSize, callback) {
4770 if(this.state == Cursor.CLOSED) {
4780 if(callback != null) {
4790 return callback(new Error("Cursor is closed"), null);
480 } else {
4810 throw new Error("Cursor is closed");
482 }
4830 } else if(batchSize != null && batchSize.constructor != Number) {
4840 if(callback != null) {
4850 return callback(new Error("batchSize requires an integer"), null);
486 } else {
4870 throw new Error("batchSize requires an integer");
488 }
489 } else {
4900 this.batchSizeValue = batchSize;
4910 if(callback != null) return callback(null, this);
492 }
493
4940 return this;
495};
496
497/**
498 * The limit used for the getMore command
499 *
500 * @return {Number} The number of records to request per batch.
501 * @ignore
502 * @api private
503 */
5041var limitRequest = function(self) {
5050 var requestedLimit = self.limitValue;
5060 var absLimitValue = Math.abs(self.limitValue);
5070 var absBatchValue = Math.abs(self.batchSizeValue);
508
5090 if(absLimitValue > 0) {
5100 if (absBatchValue > 0) {
5110 requestedLimit = Math.min(absLimitValue, absBatchValue);
512 }
513 } else {
5140 requestedLimit = self.batchSizeValue;
515 }
516
5170 return requestedLimit;
518};
519
520
521/**
522 * Generates a QueryCommand object using the parameters of this cursor.
523 *
524 * @return {QueryCommand} The command object
525 * @ignore
526 * @api private
527 */
5281var generateQueryCommand = function(self) {
529 // Unpack the options
5300 var queryOptions = QueryCommand.OPTS_NONE;
5310 if(!self.timeout) {
5320 queryOptions |= QueryCommand.OPTS_NO_CURSOR_TIMEOUT;
533 }
534
5350 if(self.tailable != null) {
5360 queryOptions |= QueryCommand.OPTS_TAILABLE_CURSOR;
5370 self.skipValue = self.limitValue = 0;
538
539 // if awaitdata is set
5400 if(self.awaitdata != null) {
5410 queryOptions |= QueryCommand.OPTS_AWAIT_DATA;
542 }
543
544 // This sets an internal undocumented flag. Clients should not depend on its
545 // behavior!
5460 if(self.oplogReplay != null) {
5470 queryOptions |= QueryCommand.OPTS_OPLOG_REPLAY;
548 }
549 }
550
5510 if(self.exhaust) {
5520 queryOptions |= QueryCommand.OPTS_EXHAUST;
553 }
554
555 // Unpack the read preference to set slave ok correctly
5560 var read = self.read instanceof ReadPreference ? self.read.mode : self.read;
557
558 // if(self.read == 'secondary')
5590 if(read == ReadPreference.PRIMARY_PREFERRED
560 || read == ReadPreference.SECONDARY
561 || read == ReadPreference.SECONDARY_PREFERRED
562 || read == ReadPreference.NEAREST) {
5630 queryOptions |= QueryCommand.OPTS_SLAVE;
564 }
565
566 // Override slaveOk from the user
5670 if(self.slaveOk) {
5680 queryOptions |= QueryCommand.OPTS_SLAVE;
569 }
570
5710 if(self.partial) {
5720 queryOptions |= QueryCommand.OPTS_PARTIAL;
573 }
574
575 // limitValue of -1 is a special case used by Db#eval
5760 var numberToReturn = self.limitValue == -1 ? -1 : limitRequest(self);
577
578 // Check if we need a special selector
5790 if(self.sortValue != null || self.explainValue != null || self.hint != null || self.snapshot != null
580 || self.returnKey != null || self.maxScan != null || self.min != null || self.max != null
581 || self.showDiskLoc != null || self.comment != null || typeof self.maxTimeMSValue == 'number') {
582
583 // Build special selector
5840 var specialSelector = {'$query':self.selector};
5850 if(self.sortValue != null) specialSelector['orderby'] = utils.formattedOrderClause(self.sortValue);
5860 if(self.hint != null && self.hint.constructor == Object) specialSelector['$hint'] = self.hint;
5870 if(self.snapshot != null) specialSelector['$snapshot'] = true;
5880 if(self.returnKey != null) specialSelector['$returnKey'] = self.returnKey;
5890 if(self.maxScan != null) specialSelector['$maxScan'] = self.maxScan;
5900 if(self.min != null) specialSelector['$min'] = self.min;
5910 if(self.max != null) specialSelector['$max'] = self.max;
5920 if(self.showDiskLoc != null) specialSelector['$showDiskLoc'] = self.showDiskLoc;
5930 if(self.comment != null) specialSelector['$comment'] = self.comment;
594
595 // If we are querying the $cmd collection we need to add maxTimeMS as a field
596 // otherwise for a normal query it's a "special selector" $maxTimeMS
5970 if(typeof self.maxTimeMSValue == 'number'
598 && self.collectionName.indexOf('.$cmd') != -1) {
5990 specialSelector['maxTimeMS'] = self.maxTimeMSValue;
6000 } else if(typeof self.maxTimeMSValue == 'number'
601 && self.collectionName.indexOf('.$cmd') == -1) {
6020 specialSelector['$maxTimeMS'] = self.maxTimeMSValue;
603 }
604
605 // If we have explain set only return a single document with automatic cursor close
6060 if(self.explainValue != null) {
6070 numberToReturn = (-1)*Math.abs(numberToReturn);
6080 specialSelector['$explain'] = true;
609 }
610
611 // Return the query
6120 return new QueryCommand(self.db, self.collectionName, queryOptions, self.skipValue, numberToReturn, specialSelector, self.fields);
613 } else {
6140 return new QueryCommand(self.db, self.collectionName, queryOptions, self.skipValue, numberToReturn, self.selector, self.fields);
615 }
616};
617
618/**
619 * @return {Object} Returns an object containing the sort value of this cursor with
620 * the proper formatting that can be used internally in this cursor.
621 * @ignore
622 * @api private
623 */
6241Cursor.prototype.formattedOrderClause = function() {
6250 return utils.formattedOrderClause(this.sortValue);
626};
627
628/**
629 * Converts the value of the sort direction into its equivalent numerical value.
630 *
631 * @param sortDirection {String|number} Range of acceptable values:
632 * 'ascending', 'descending', 'asc', 'desc', 1, -1
633 *
634 * @return {number} The equivalent numerical value
635 * @throws Error if the given sortDirection is invalid
636 * @ignore
637 * @api private
638 */
6391Cursor.prototype.formatSortValue = function(sortDirection) {
6400 return utils.formatSortValue(sortDirection);
641};
642
643/**
644 * Gets the next document from the cursor.
645 *
646 * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object on error while the second parameter will contain a document from the returned result or null if there are no more results.
647 * @api public
648 */
6491Cursor.prototype.nextObject = function(options, callback) {
6500 var self = this;
651
6520 if(typeof options == 'function') {
6530 callback = options;
6540 options = {};
655 }
656
6570 if(self.state == Cursor.INIT) {
6580 var cmd;
6590 try {
6600 cmd = generateQueryCommand(self);
661 } catch (err) {
6620 return callback(err, null);
663 }
664
665 // No need to check the keys
6660 var queryOptions = {exhaust: self.exhaust
667 , raw:self.raw
668 , read:self.read
669 , connection:self.connection
670 , checkKeys: false};
671
672 // Execute command
6730 var commandHandler = function(err, result) {
674 // If on reconnect, the command got given a different connection, switch
675 // the whole cursor to it.
6760 self.connection = queryOptions.connection;
6770 self.state = Cursor.OPEN;
6780 if(err != null && result == null) return callback(utils.toError(err), null);
679
6800 if(err == null && (result == null || result.documents == null || !Array.isArray(result.documents))) {
6810 return self.close(function() {callback(new Error("command failed to return results"), null);});
682 }
683
6840 if(err == null && result && result.documents[0] && result.documents[0]['$err']) {
6850 return self.close(function() {callback(utils.toError(result.documents[0]['$err']), null);});
686 }
687
6880 if(err == null && result && result.documents[0] && result.documents[0]['errmsg']) {
6890 return self.close(function() {callback(utils.toError(result.documents[0]), null);});
690 }
691
6920 self.queryRun = true;
6930 self.state = Cursor.OPEN; // Adjust the state of the cursor
6940 self.cursorId = result.cursorId;
6950 self.totalNumberOfRecords = result.numberReturned;
696
697 // Add the new documents to the list of items, using forloop to avoid
698 // new array allocations and copying
6990 for(var i = 0; i < result.documents.length; i++) {
7000 self.items.push(result.documents[i]);
701 }
702
703 // If we have noReturn set just return (not modifying the internal item list)
704 // used for toArray
7050 if(options.noReturn) {
7060 return callback(null, true);
707 }
708
709 // Ignore callbacks until the cursor is dead for exhausted
7100 if(self.exhaust && result.cursorId.toString() == "0") {
7110 self.nextObject(callback);
7120 } else if(self.exhaust == false || self.exhaust == null) {
7130 self.nextObject(callback);
714 }
715 };
716
717 // If we have no connection set on this cursor check one out
7180 if(self.connection == null) {
7190 try {
7200 self.connection = self.db.serverConfig.checkoutReader(this.read);
721 // Add to the query options
7220 queryOptions.connection = self.connection;
723 } catch(err) {
7240 return callback(utils.toError(err), null);
725 }
726 }
727
728 // Execute the command
7290 self.db._executeQueryCommand(cmd, queryOptions, commandHandler);
730 // Set the command handler to null
7310 commandHandler = null;
7320 } else if(self.items.length) {
7330 callback(null, self.items.shift());
7340 } else if(self.cursorId.greaterThan(Long.fromInt(0))) {
7350 getMore(self, callback);
736 } else {
737 // Force cursor to stay open
7380 return self.close(function() {callback(null, null);});
739 }
740}
741
742/**
743 * Gets more results from the database if any.
744 *
745 * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object on error while the second parameter will contain a document from the returned result or null if there are no more results.
746 * @ignore
747 * @api private
748 */
7491var getMore = function(self, options, callback) {
7500 var limit = 0;
751
7520 if(typeof options == 'function') {
7530 callback = options;
7540 options = {};
755 }
756
7570 if(self.state == Cursor.GET_MORE) return callback(null, null);
758
759 // Set get more in progress
7600 self.state = Cursor.GET_MORE;
761
762 // Set options
7630 if (!self.tailable && self.limitValue > 0) {
7640 limit = self.limitValue - self.totalNumberOfRecords;
7650 if (limit < 1) {
7660 self.close(function() {callback(null, null);});
7670 return;
768 }
769 }
770
7710 try {
7720 var getMoreCommand = new GetMoreCommand(
773 self.db
774 , self.collectionName
775 , limitRequest(self)
776 , self.cursorId
777 );
778
779 // Set up options
7800 var command_options = {read: self.read, raw: self.raw, connection:self.connection };
781
782 // Execute the command
7830 self.db._executeQueryCommand(getMoreCommand, command_options, function(err, result) {
7840 var cbValue;
785
786 // Get more done
7870 self.state = Cursor.OPEN;
788
7890 if(err != null) {
7900 self.state = Cursor.CLOSED;
7910 return callback(utils.toError(err), null);
792 }
793
794 // Ensure we get a valid result
7950 if(!result || !result.documents) {
7960 self.state = Cursor.CLOSED;
7970 return callback(utils.toError("command failed to return results"), null)
798 }
799
800 // If the QueryFailure flag is set
8010 if((result.responseFlag & (1 << 1)) != 0) {
8020 self.state = Cursor.CLOSED;
8030 return callback(utils.toError("QueryFailure flag set on getmore command"), null);
804 }
805
8060 try {
8070 var isDead = 1 === result.responseFlag && result.cursorId.isZero();
808
8090 self.cursorId = result.cursorId;
8100 self.totalNumberOfRecords += result.numberReturned;
811
812 // Determine if there's more documents to fetch
8130 if(result.numberReturned > 0) {
8140 if (self.limitValue > 0) {
8150 var excessResult = self.totalNumberOfRecords - self.limitValue;
816
8170 if (excessResult > 0) {
8180 result.documents.splice(-1 * excessResult, excessResult);
819 }
820 }
821
822 // Reset the tries for awaitdata if we are using it
8230 self.currentNumberOfRetries = self.numberOfRetries;
824 // Get the documents
8250 for(var i = 0; i < result.documents.length; i++) {
8260 self.items.push(result.documents[i]);
827 }
828
829 // Don's shift a document out as we need it for toArray
8300 if(options.noReturn) {
8310 cbValue = true;
832 } else {
8330 cbValue = self.items.shift();
834 }
8350 } else if(self.tailable && !isDead && self.awaitdata) {
836 // Excute the tailable cursor once more, will timeout after ~4 sec if awaitdata used
8370 self.currentNumberOfRetries = self.currentNumberOfRetries - 1;
8380 if(self.currentNumberOfRetries == 0) {
8390 self.close(function() {
8400 callback(new Error("tailable cursor timed out"), null);
841 });
842 } else {
8430 getMore(self, callback);
844 }
8450 } else if(self.tailable && !isDead) {
8460 self.getMoreTimer = setTimeout(function() { getMore(self, callback); }, self.tailableRetryInterval);
847 } else {
8480 self.close(function() {callback(null, null); });
849 }
850
8510 result = null;
852 } catch(err) {
8530 callback(utils.toError(err), null);
854 }
8550 if (cbValue != null) callback(null, cbValue);
856 });
857
8580 getMoreCommand = null;
859 } catch(err) {
860 // Get more done
8610 self.state = Cursor.OPEN;
862
8630 var handleClose = function() {
8640 callback(utils.toError(err), null);
865 };
866
8670 self.close(handleClose);
8680 handleClose = null;
869 }
870}
871
872/**
873 * Gets a detailed information about how the query is performed on this cursor and how
874 * long it took the database to process it.
875 *
876 * @param {Function} callback this will be called after executing this method. The first parameter will always be null while the second parameter will be an object containing the details.
877 * @api public
878 */
8791Cursor.prototype.explain = function(callback) {
8800 var limit = (-1)*Math.abs(this.limitValue);
881
882 // Create a new cursor and fetch the plan
8830 var cursor = new Cursor(this.db, this.collection, this.selector, this.fields, {
884 skip: this.skipValue
885 , limit:limit
886 , sort: this.sortValue
887 , hint: this.hint
888 , explain: true
889 , snapshot: this.snapshot
890 , timeout: this.timeout
891 , tailable: this.tailable
892 , batchSize: this.batchSizeValue
893 , slaveOk: this.slaveOk
894 , raw: this.raw
895 , read: this.read
896 , returnKey: this.returnKey
897 , maxScan: this.maxScan
898 , min: this.min
899 , max: this.max
900 , showDiskLoc: this.showDiskLoc
901 , comment: this.comment
902 , awaitdata: this.awaitdata
903 , oplogReplay: this.oplogReplay
904 , numberOfRetries: this.numberOfRetries
905 , dbName: this.dbName
906 });
907
908 // Fetch the explaination document
9090 cursor.nextObject(function(err, item) {
9100 if(err != null) return callback(utils.toError(err), null);
911 // close the cursor
9120 cursor.close(function(err, result) {
9130 if(err != null) return callback(utils.toError(err), null);
9140 callback(null, item);
915 });
916 });
917};
918
919/**
920 * Returns a Node ReadStream interface for this cursor.
921 *
922 * Options
923 * - **transform** {Function} function of type function(object) { return transformed }, allows for transformation of data before emitting.
924 *
925 * @return {CursorStream} returns a stream object.
926 * @api public
927 */
9281Cursor.prototype.stream = function stream(options) {
9290 return new CursorStream(this, options);
930}
931
932/**
933 * Close the cursor.
934 *
935 * @param {Function} callback this will be called after executing this method. The first parameter will always contain null while the second parameter will contain a reference to this cursor.
936 * @return {null}
937 * @api public
938 */
9391Cursor.prototype.close = function(callback) {
9400 var self = this
9410 this.getMoreTimer && clearTimeout(this.getMoreTimer);
942 // Close the cursor if not needed
9430 if(this.cursorId instanceof Long && this.cursorId.greaterThan(Long.fromInt(0))) {
9440 try {
9450 var command = new KillCursorCommand(this.db, [this.cursorId]);
946 // Added an empty callback to ensure we don't throw any null exceptions
9470 this.db._executeQueryCommand(command, {read:self.read, raw:self.raw, connection:self.connection});
948 } catch(err) {}
949 }
950
951 // Null out the connection
9520 self.connection = null;
953 // Reset cursor id
9540 this.cursorId = Long.fromInt(0);
955 // Set to closed status
9560 this.state = Cursor.CLOSED;
957
9580 if(callback) {
9590 callback(null, self);
9600 self.items = [];
961 }
962
9630 return this;
964};
965
966/**
967 * Check if the cursor is closed or open.
968 *
969 * @return {Boolean} returns the state of the cursor.
970 * @api public
971 */
9721Cursor.prototype.isClosed = function() {
9730 return this.state == Cursor.CLOSED ? true : false;
974};
975
976/**
977 * Init state
978 *
979 * @classconstant INIT
980 **/
9811Cursor.INIT = 0;
982
983/**
984 * Cursor open
985 *
986 * @classconstant OPEN
987 **/
9881Cursor.OPEN = 1;
989
990/**
991 * Cursor closed
992 *
993 * @classconstant CLOSED
994 **/
9951Cursor.CLOSED = 2;
996
997/**
998 * Cursor performing a get more
999 *
1000 * @classconstant OPEN
1001 **/
10021Cursor.GET_MORE = 3;
1003
1004/**
1005 * @ignore
1006 * @api private
1007 */
10081exports.Cursor = Cursor;
1009

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursorstream.js

25%
55
14
41
LineHitsSource
11var timers = require('timers');
2
3// Set processor, setImmediate if 0.10 otherwise nextTick
41var processor = require('./utils').processor();
5
6/**
7 * Module dependecies.
8 */
91var Stream = require('stream').Stream;
10
11/**
12 * CursorStream
13 *
14 * Returns a stream interface for the **cursor**.
15 *
16 * Options
17 * - **transform** {Function} function of type function(object) { return transformed }, allows for transformation of data before emitting.
18 *
19 * Events
20 * - **data** {function(item) {}} the data event triggers when a document is ready.
21 * - **error** {function(err) {}} the error event triggers if an error happens.
22 * - **close** {function() {}} the end event triggers when there is no more documents available.
23 *
24 * @class Represents a CursorStream.
25 * @param {Cursor} cursor a cursor object that the stream wraps.
26 * @return {Stream}
27 */
281function CursorStream(cursor, options) {
290 if(!(this instanceof CursorStream)) return new CursorStream(cursor);
300 options = options ? options : {};
31
320 Stream.call(this);
33
340 this.readable = true;
350 this.paused = false;
360 this._cursor = cursor;
370 this._destroyed = null;
380 this.options = options;
39
40 // give time to hook up events
410 var self = this;
420 process.nextTick(function() {
430 self._init();
44 });
45}
46
47/**
48 * Inherit from Stream
49 * @ignore
50 * @api private
51 */
521CursorStream.prototype.__proto__ = Stream.prototype;
53
54/**
55 * Flag stating whether or not this stream is readable.
56 */
571CursorStream.prototype.readable;
58
59/**
60 * Flag stating whether or not this stream is paused.
61 */
621CursorStream.prototype.paused;
63
64/**
65 * Initialize the cursor.
66 * @ignore
67 * @api private
68 */
691CursorStream.prototype._init = function () {
700 if (this._destroyed) return;
710 this._next();
72}
73
74/**
75 * Pull the next document from the cursor.
76 * @ignore
77 * @api private
78 */
791CursorStream.prototype._next = function () {
800 if(this.paused || this._destroyed) return;
81
820 var self = this;
83 // Get the next object
840 processor(function() {
850 if(self.paused || self._destroyed) return;
86
870 self._cursor.nextObject(function (err, doc) {
880 self._onNextObject(err, doc);
89 });
90 });
91}
92
93/**
94 * Handle each document as its returned from the cursor.
95 * @ignore
96 * @api private
97 */
981CursorStream.prototype._onNextObject = function (err, doc) {
990 if(err) return this.destroy(err);
100
101 // when doc is null we hit the end of the cursor
1020 if(!doc && (this._cursor.state == 1 || this._cursor.state == 2)) {
1030 this.emit('end')
1040 return this.destroy();
1050 } else if(doc) {
1060 var data = typeof this.options.transform == 'function' ? this.options.transform(doc) : doc;
1070 this.emit('data', data);
1080 this._next();
109 }
110}
111
112/**
113 * Pauses the stream.
114 *
115 * @api public
116 */
1171CursorStream.prototype.pause = function () {
1180 this.paused = true;
119}
120
121/**
122 * Resumes the stream.
123 *
124 * @api public
125 */
1261CursorStream.prototype.resume = function () {
1270 var self = this;
128
129 // Don't do anything if we are not paused
1300 if(!this.paused) return;
1310 if(!this._cursor.state == 3) return;
132
1330 process.nextTick(function() {
1340 self.paused = false;
135 // Only trigger more fetching if the cursor is open
1360 self._next();
137 })
138}
139
140/**
141 * Destroys the stream, closing the underlying
142 * cursor. No more events will be emitted.
143 *
144 * @api public
145 */
1461CursorStream.prototype.destroy = function (err) {
1470 if (this._destroyed) return;
1480 this._destroyed = true;
1490 this.readable = false;
150
1510 this._cursor.close();
152
1530 if(err) {
1540 this.emit('error', err);
155 }
156
1570 this.emit('close');
158}
159
160// TODO - maybe implement the raw option to pass binary?
161//CursorStream.prototype.setEncoding = function () {
162//}
163
1641module.exports = exports = CursorStream;
165

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js

16%
753
125
628
LineHitsSource
1/**
2 * Module dependencies.
3 * @ignore
4 */
51var QueryCommand = require('./commands/query_command').QueryCommand
6 , DbCommand = require('./commands/db_command').DbCommand
7 , MongoReply = require('./responses/mongo_reply').MongoReply
8 , Admin = require('./admin').Admin
9 , Collection = require('./collection').Collection
10 , Server = require('./connection/server').Server
11 , ReplSet = require('./connection/repl_set/repl_set').ReplSet
12 , ReadPreference = require('./connection/read_preference').ReadPreference
13 , Mongos = require('./connection/mongos').Mongos
14 , Cursor = require('./cursor').Cursor
15 , EventEmitter = require('events').EventEmitter
16 , inherits = require('util').inherits
17 , crypto = require('crypto')
18 , timers = require('timers')
19 , utils = require('./utils')
20
21 // Authentication methods
22 , mongodb_cr_authenticate = require('./auth/mongodb_cr.js').authenticate
23 , mongodb_gssapi_authenticate = require('./auth/mongodb_gssapi.js').authenticate
24 , mongodb_sspi_authenticate = require('./auth/mongodb_sspi.js').authenticate
25 , mongodb_plain_authenticate = require('./auth/mongodb_plain.js').authenticate
26 , mongodb_x509_authenticate = require('./auth/mongodb_x509.js').authenticate;
27
281var hasKerberos = false;
29// Check if we have a the kerberos library
301try {
311 require('kerberos');
321 hasKerberos = true;
33} catch(err) {}
34
35// Set processor, setImmediate if 0.10 otherwise nextTick
361var processor = require('./utils').processor();
37
38/**
39 * Create a new Db instance.
40 *
41 * Options
42 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
43 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
44 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
45 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
46 * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
47 * - **native_parser** {Boolean, default:false}, use c++ bson parser.
48 * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client.
49 * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
50 * - **serializeFunctions** {Boolean, default:false}, serialize functions.
51 * - **raw** {Boolean, default:false}, perform operations using raw bson buffers.
52 * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution.
53 * - **retryMiliSeconds** {Number, default:5000}, number of milliseconds between retries.
54 * - **numberOfRetries** {Number, default:5}, number of retries off connection.
55 * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**.
56 * - **slaveOk** {Number, default:null}, force setting of SlaveOk flag on queries (only use when explicitly connecting to a secondary server).
57 * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits
58 * - **bufferMaxEntries** {Boolean, default: -1}, sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited
59 *
60 * Deprecated Options
61 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
62 *
63 * @class Represents a Db
64 * @param {String} databaseName name of the database.
65 * @param {Object} serverConfig server config object.
66 * @param {Object} [options] additional options for the collection.
67 */
681function Db(databaseName, serverConfig, options) {
691 if(!(this instanceof Db)) return new Db(databaseName, serverConfig, options);
701 EventEmitter.call(this);
711 var self = this;
721 this.databaseName = databaseName;
731 this.serverConfig = serverConfig;
741 this.options = options == null ? {} : options;
75 // State to check against if the user force closed db
761 this._applicationClosed = false;
77 // Fetch the override flag if any
781 var overrideUsedFlag = this.options['override_used_flag'] == null ? false : this.options['override_used_flag'];
79
80 // Verify that nobody is using this config
811 if(!overrideUsedFlag && this.serverConfig != null && typeof this.serverConfig == 'object' && this.serverConfig._isUsed && this.serverConfig._isUsed()) {
820 throw new Error('A Server or ReplSet instance cannot be shared across multiple Db instances');
831 } else if(!overrideUsedFlag && typeof this.serverConfig == 'object'){
84 // Set being used
851 this.serverConfig._used = true;
86 }
87
88 // Allow slaveOk override
891 this.slaveOk = this.options['slave_ok'] == null ? false : this.options['slave_ok'];
901 this.slaveOk = this.options['slaveOk'] == null ? this.slaveOk : this.options['slaveOk'];
91
92 // Number of operations to buffer before failure
931 this.bufferMaxEntries = typeof this.options['bufferMaxEntries'] == 'number' ? this.options['bufferMaxEntries'] : -1;
94
95 // Ensure we have a valid db name
961 validateDatabaseName(databaseName);
97
98 // Contains all the connections for the db
991 try {
1001 this.native_parser = this.options.native_parser;
101 // The bson lib
1021 var bsonLib = this.bsonLib = this.options.native_parser ? require('bson').BSONNative : require('bson').BSONPure;
103 // Fetch the serializer object
1041 var BSON = bsonLib.BSON;
105
106 // Create a new instance
1071 this.bson = new BSON([bsonLib.Long, bsonLib.ObjectID, bsonLib.Binary, bsonLib.Code, bsonLib.DBRef, bsonLib.Symbol, bsonLib.Double, bsonLib.Timestamp, bsonLib.MaxKey, bsonLib.MinKey]);
1081 this.bson.promoteLongs = this.options.promoteLongs == null ? true : this.options.promoteLongs;
109
110 // Backward compatibility to access types
1111 this.bson_deserializer = bsonLib;
1121 this.bson_serializer = bsonLib;
113
114 // Add any overrides to the serializer and deserializer
1151 this.bson_deserializer.promoteLongs = this.options.promoteLongs == null ? true : this.options.promoteLongs;
116 } catch (err) {
117 // If we tried to instantiate the native driver
1180 var msg = 'Native bson parser not compiled, please compile '
119 + 'or avoid using native_parser=true';
1200 throw Error(msg);
121 }
122
123 // Internal state of the server
1241 this._state = 'disconnected';
125
1261 this.pkFactory = this.options.pk == null ? bsonLib.ObjectID : this.options.pk;
1271 this.forceServerObjectId = this.options.forceServerObjectId != null ? this.options.forceServerObjectId : false;
128
129 // Added safe
1301 this.safe = this.options.safe == null ? false : this.options.safe;
131
132 // If we have not specified a "safe mode" we just print a warning to the console
1331 if(this.options.safe == null && this.options.w == null && this.options.journal == null && this.options.fsync == null) {
1340 console.log("========================================================================================");
1350 console.log("= Please ensure that you set the default write concern for the database by setting =");
1360 console.log("= one of the options =");
1370 console.log("= =");
1380 console.log("= w: (value of > -1 or the string 'majority'), where < 1 means =");
1390 console.log("= no write acknowledgement =");
1400 console.log("= journal: true/false, wait for flush to journal before acknowledgement =");
1410 console.log("= fsync: true/false, wait for flush to file system before acknowledgement =");
1420 console.log("= =");
1430 console.log("= For backward compatibility safe is still supported and =");
1440 console.log("= allows values of [true | false | {j:true} | {w:n, wtimeout:n} | {fsync:true}] =");
1450 console.log("= the default value is false which means the driver receives does not =");
1460 console.log("= return the information of the success/error of the insert/update/remove =");
1470 console.log("= =");
1480 console.log("= ex: new Db(new Server('localhost', 27017), {safe:false}) =");
1490 console.log("= =");
1500 console.log("= http://www.mongodb.org/display/DOCS/getLastError+Command =");
1510 console.log("= =");
1520 console.log("= The default of no acknowledgement will change in the very near future =");
1530 console.log("= =");
1540 console.log("= This message will disappear when the default safe is set on the driver Db =");
1550 console.log("========================================================================================");
156 }
157
158 // Internal states variables
1591 this.notReplied ={};
1601 this.isInitializing = true;
1611 this.openCalled = false;
162
163 // Command queue, keeps a list of incoming commands that need to be executed once the connection is up
1641 this.commands = [];
165
166 // Set up logger
1671 this.logger = this.options.logger != null
168 && (typeof this.options.logger.debug == 'function')
169 && (typeof this.options.logger.error == 'function')
170 && (typeof this.options.logger.log == 'function')
171 ? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}};
172
173 // Associate the logger with the server config
1741 this.serverConfig.logger = this.logger;
1751 if(this.serverConfig.strategyInstance) this.serverConfig.strategyInstance.logger = this.logger;
1761 this.tag = new Date().getTime();
177 // Just keeps list of events we allow
1781 this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[]};
179
180 // Controls serialization options
1811 this.serializeFunctions = this.options.serializeFunctions != null ? this.options.serializeFunctions : false;
182
183 // Raw mode
1841 this.raw = this.options.raw != null ? this.options.raw : false;
185
186 // Record query stats
1871 this.recordQueryStats = this.options.recordQueryStats != null ? this.options.recordQueryStats : false;
188
189 // If we have server stats let's make sure the driver objects have it enabled
1901 if(this.recordQueryStats == true) {
1910 this.serverConfig.enableRecordQueryStats(true);
192 }
193
194 // Retry information
1951 this.retryMiliSeconds = this.options.retryMiliSeconds != null ? this.options.retryMiliSeconds : 1000;
1961 this.numberOfRetries = this.options.numberOfRetries != null ? this.options.numberOfRetries : 60;
197
198 // Set default read preference if any
1991 this.readPreference = this.options.readPreference;
200
201 // Set read preference on serverConfig if none is set
202 // but the db one was
2031 if(this.serverConfig.options.readPreference == null
204 && this.readPreference != null) {
2050 this.serverConfig.setReadPreference(this.readPreference);
206 }
207
208 // Ensure we keep a reference to this db
2091 this.serverConfig._dbStore.add(this);
210};
211
212/**
213 * @ignore
214 */
2151function validateDatabaseName(databaseName) {
2161 if(typeof databaseName !== 'string') throw new Error("database name must be a string");
2171 if(databaseName.length === 0) throw new Error("database name cannot be the empty string");
2181 if(databaseName == '$external') return;
219
2201 var invalidChars = [" ", ".", "$", "/", "\\"];
2211 for(var i = 0; i < invalidChars.length; i++) {
2225 if(databaseName.indexOf(invalidChars[i]) != -1) throw new Error("database names cannot contain the character '" + invalidChars[i] + "'");
223 }
224}
225
226/**
227 * @ignore
228 */
2291inherits(Db, EventEmitter);
230
231/**
232 * Initialize the database connection.
233 *
234 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the index information or null if an error occurred.
235 * @return {null}
236 * @api public
237 */
2381Db.prototype.open = function(callback) {
2391 var self = this;
240
241 // Check that the user has not called this twice
2421 if(this.openCalled) {
243 // Close db
2440 this.close();
245 // Throw error
2460 throw new Error("db object already connecting, open cannot be called multiple times");
247 }
248
249 // If we have a specified read preference
2501 if(this.readPreference != null) this.serverConfig.setReadPreference(this.readPreference);
251
252 // Set that db has been opened
2531 this.openCalled = true;
254
255 // Set the status of the server
2561 self._state = 'connecting';
257
258 // Set up connections
2591 if(self.serverConfig instanceof Server || self.serverConfig instanceof ReplSet || self.serverConfig instanceof Mongos) {
260 // Ensure we have the original options passed in for the server config
2611 var connect_options = {};
2621 for(var name in self.serverConfig.options) {
2632 connect_options[name] = self.serverConfig.options[name]
264 }
2651 connect_options.firstCall = true;
266
267 // Attempt to connect
2681 self.serverConfig.connect(self, connect_options, function(err, result) {
2690 if(err != null) {
270 // Close db to reset connection
2710 return self.close(function () {
272 // Return error from connection
2730 return callback(err, null);
274 });
275 }
276 // Set the status of the server
2770 self._state = 'connected';
278 // If we have queued up commands execute a command to trigger replays
2790 if(self.commands.length > 0) _execute_queued_command(self);
280 // Callback
2810 process.nextTick(function() {
2820 try {
2830 callback(null, self);
284 } catch(err) {
2850 self.close();
2860 throw err;
287 }
288 });
289 });
290 } else {
2910 try {
2920 callback(Error("Server parameter must be of type Server, ReplSet or Mongos"), null);
293 } catch(err) {
2940 self.close();
2950 throw err;
296 }
297 }
298};
299
300/**
301 * Create a new Db instance sharing the current socket connections.
302 *
303 * @param {String} dbName the name of the database we want to use.
304 * @return {Db} a db instance using the new database.
305 * @api public
306 */
3071Db.prototype.db = function(dbName) {
308 // Copy the options and add out internal override of the not shared flag
3090 var options = {};
3100 for(var key in this.options) {
3110 options[key] = this.options[key];
312 }
313
314 // Add override flag
3150 options['override_used_flag'] = true;
316 // Check if the db already exists and reuse if it's the case
3170 var db = this.serverConfig._dbStore.fetch(dbName);
318
319 // Create a new instance
3200 if(!db) {
3210 db = new Db(dbName, this.serverConfig, options);
322 }
323
324 // Return the db object
3250 return db;
326};
327
328/**
329 * Close the current db connection, including all the child db instances. Emits close event if no callback is provided.
330 *
331 * @param {Boolean} [forceClose] connection can never be reused.
332 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results or null if an error occurred.
333 * @return {null}
334 * @api public
335 */
3361Db.prototype.close = function(forceClose, callback) {
3370 var self = this;
338 // Ensure we force close all connections
3390 this._applicationClosed = false;
340
3410 if(typeof forceClose == 'function') {
3420 callback = forceClose;
3430 } else if(typeof forceClose == 'boolean') {
3440 this._applicationClosed = forceClose;
345 }
346
3470 this.serverConfig.close(function(err, result) {
348 // You can reuse the db as everything is shut down
3490 self.openCalled = false;
350 // If we have a callback call it
3510 if(callback) callback(err, result);
352 });
353};
354
355/**
356 * Access the Admin database
357 *
358 * @param {Function} [callback] returns the results.
359 * @return {Admin} the admin db object.
360 * @api public
361 */
3621Db.prototype.admin = function(callback) {
3630 if(callback == null) return new Admin(this);
3640 callback(null, new Admin(this));
365};
366
367/**
368 * Returns a cursor to all the collection information.
369 *
370 * @param {String} [collectionName] the collection name we wish to retrieve the information from.
371 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the options or null if an error occurred.
372 * @return {null}
373 * @api public
374 */
3751Db.prototype.collectionsInfo = function(collectionName, callback) {
3760 if(callback == null && typeof collectionName == 'function') { callback = collectionName; collectionName = null; }
377 // Create selector
3780 var selector = {};
379 // If we are limiting the access to a specific collection name
3800 if(collectionName != null) selector.name = this.databaseName + "." + collectionName;
381
382 // Return Cursor
383 // callback for backward compatibility
3840 if(callback) {
3850 callback(null, new Cursor(this, new Collection(this, DbCommand.SYSTEM_NAMESPACE_COLLECTION), selector));
386 } else {
3870 return new Cursor(this, new Collection(this, DbCommand.SYSTEM_NAMESPACE_COLLECTION), selector);
388 }
389};
390
391/**
392 * Get the list of all collection names for the specified db
393 *
394 * Options
395 * - **namesOnly** {String, default:false}, Return only the full collection namespace.
396 *
397 * @param {String} [collectionName] the collection name we wish to filter by.
398 * @param {Object} [options] additional options during update.
399 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collection names or null if an error occurred.
400 * @return {null}
401 * @api public
402 */
4031Db.prototype.collectionNames = function(collectionName, options, callback) {
4040 var self = this;
4050 var args = Array.prototype.slice.call(arguments, 0);
4060 callback = args.pop();
4070 collectionName = args.length ? args.shift() : null;
4080 options = args.length ? args.shift() || {} : {};
409
410 // Ensure no breaking behavior
4110 if(collectionName != null && typeof collectionName == 'object') {
4120 options = collectionName;
4130 collectionName = null;
414 }
415
416 // Let's make our own callback to reuse the existing collections info method
4170 self.collectionsInfo(collectionName, function(err, cursor) {
4180 if(err != null) return callback(err, null);
419
4200 cursor.toArray(function(err, documents) {
4210 if(err != null) return callback(err, null);
422
423 // List of result documents that have been filtered
4240 var filtered_documents = documents.filter(function(document) {
4250 return !(document.name.indexOf(self.databaseName) == -1 || document.name.indexOf('$') != -1);
426 });
427
428 // If we are returning only the names
4290 if(options.namesOnly) {
4300 filtered_documents = filtered_documents.map(function(document) { return document.name });
431 }
432
433 // Return filtered items
4340 callback(null, filtered_documents);
435 });
436 });
437};
438
439/**
440 * Fetch a specific collection (containing the actual collection information). If the application does not use strict mode you can
441 * can use it without a callback in the following way. var collection = db.collection('mycollection');
442 *
443 * Options
444* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
445 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
446 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
447 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
448 * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
449 * - **raw** {Boolean, default:false}, perform all operations using raw bson objects.
450 * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
451 * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
452 * - **strict**, (Boolean, default:false) returns an error if the collection does not exist
453 *
454 * Deprecated Options
455 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
456 *
457 * @param {String} collectionName the collection name we wish to access.
458 * @param {Object} [options] returns option results.
459 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collection or null if an error occurred.
460 * @return {null}
461 * @api public
462 */
4631Db.prototype.collection = function(collectionName, options, callback) {
4640 var self = this;
4650 if(typeof options === "function") { callback = options; options = {}; }
466 // Execute safe
467
4680 if(options && (options.strict)) {
4690 self.collectionNames(collectionName, function(err, collections) {
4700 if(err != null) return callback(err, null);
471
4720 if(collections.length == 0) {
4730 return callback(new Error("Collection " + collectionName + " does not exist. Currently in safe mode."), null);
474 } else {
4750 try {
4760 var collection = new Collection(self, collectionName, self.pkFactory, options);
477 } catch(err) {
4780 return callback(err, null);
479 }
4800 return callback(null, collection);
481 }
482 });
483 } else {
4840 try {
4850 var collection = new Collection(self, collectionName, self.pkFactory, options);
486 } catch(err) {
4870 if(callback == null) {
4880 throw err;
489 } else {
4900 return callback(err, null);
491 }
492 }
493
494 // If we have no callback return collection object
4950 return callback == null ? collection : callback(null, collection);
496 }
497};
498
499/**
500 * Fetch all collections for the current db.
501 *
502 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collections or null if an error occurred.
503 * @return {null}
504 * @api public
505 */
5061Db.prototype.collections = function(callback) {
5070 var self = this;
508 // Let's get the collection names
5090 self.collectionNames(function(err, documents) {
5100 if(err != null) return callback(err, null);
5110 var collections = [];
5120 documents.forEach(function(document) {
5130 collections.push(new Collection(self, document.name.replace(self.databaseName + ".", ''), self.pkFactory));
514 });
515 // Return the collection objects
5160 callback(null, collections);
517 });
518};
519
520/**
521 * Evaluate javascript on the server
522 *
523 * Options
524 * - **nolock** {Boolean, default:false}, Tell MongoDB not to block on the evaulation of the javascript.
525 *
526 * @param {Code} code javascript to execute on server.
527 * @param {Object|Array} [parameters] the parameters for the call.
528 * @param {Object} [options] the options
529 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from eval or null if an error occurred.
530 * @return {null}
531 * @api public
532 */
5331Db.prototype.eval = function(code, parameters, options, callback) {
534 // Unpack calls
5350 var args = Array.prototype.slice.call(arguments, 1);
5360 callback = args.pop();
5370 parameters = args.length ? args.shift() : parameters;
5380 options = args.length ? args.shift() || {} : {};
539
5400 var finalCode = code;
5410 var finalParameters = [];
542 // If not a code object translate to one
5430 if(!(finalCode instanceof this.bsonLib.Code)) {
5440 finalCode = new this.bsonLib.Code(finalCode);
545 }
546
547 // Ensure the parameters are correct
5480 if(parameters != null && parameters.constructor != Array && typeof parameters !== 'function') {
5490 finalParameters = [parameters];
5500 } else if(parameters != null && parameters.constructor == Array && typeof parameters !== 'function') {
5510 finalParameters = parameters;
552 }
553
554 // Create execution selector
5550 var selector = {'$eval':finalCode, 'args':finalParameters};
556 // Check if the nolock parameter is passed in
5570 if(options['nolock']) {
5580 selector['nolock'] = options['nolock'];
559 }
560
561 // Set primary read preference
5620 options.readPreference = ReadPreference.PRIMARY;
563
564 // Execute the eval
5650 this.collection(DbCommand.SYSTEM_COMMAND_COLLECTION).findOne(selector, options, function(err, result) {
5660 if(err) return callback(err);
567
5680 if(result && result.ok == 1) {
5690 callback(null, result.retval);
5700 } else if(result) {
5710 callback(new Error("eval failed: " + result.errmsg), null); return;
572 } else {
5730 callback(err, result);
574 }
575 });
576};
577
578/**
579 * Dereference a dbref, against a db
580 *
581 * @param {DBRef} dbRef db reference object we wish to resolve.
582 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dereference or null if an error occurred.
583 * @return {null}
584 * @api public
585 */
5861Db.prototype.dereference = function(dbRef, callback) {
5870 var db = this;
588 // If we have a db reference then let's get the db first
5890 if(dbRef.db != null) db = this.db(dbRef.db);
590 // Fetch the collection and find the reference
5910 var collection = db.collection(dbRef.namespace);
5920 collection.findOne({'_id':dbRef.oid}, function(err, result) {
5930 callback(err, result);
594 });
595};
596
597/**
598 * Logout user from server, fire off on all connections and remove all auth info
599 *
600 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from logout or null if an error occurred.
601 * @return {null}
602 * @api public
603 */
6041Db.prototype.logout = function(options, callback) {
6050 var self = this;
606 // Unpack calls
6070 var args = Array.prototype.slice.call(arguments, 0);
6080 callback = args.pop();
6090 options = args.length ? args.shift() || {} : {};
610
611 // Number of connections we need to logout from
6120 var numberOfConnections = this.serverConfig.allRawConnections().length;
613
614 // Let's generate the logout command object
6150 var logoutCommand = DbCommand.logoutCommand(self, {logout:1}, options);
6160 self._executeQueryCommand(logoutCommand, {onAll:true}, function(err, result) {
617 // Count down
6180 numberOfConnections = numberOfConnections - 1;
619 // Work around the case where the number of connections are 0
6200 if(numberOfConnections <= 0 && typeof callback == 'function') {
6210 var internalCallback = callback;
6220 callback = null;
623
624 // Remove the db from auths
6250 self.serverConfig.auth.remove(self.databaseName);
626
627 // Handle error result
6280 utils.handleSingleCommandResultReturn(true, false, internalCallback)(err, result);
629 }
630 });
631};
632
633/**
634 * Authenticate a user against the server.
635 * authMechanism
636 * Options
637 * - **authMechanism** {String, default:MONGODB-CR}, The authentication mechanism to use, GSSAPI or MONGODB-CR
638 *
639 * @param {String} username username.
640 * @param {String} password password.
641 * @param {Object} [options] the options
642 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from authentication or null if an error occurred.
643 * @return {null}
644 * @api public
645 */
6461Db.prototype.authenticate = function(username, password, options, callback) {
6470 var self = this;
648
6490 if(typeof options == 'function') {
6500 callback = options;
6510 options = {};
652 }
653
654 // Set default mechanism
6550 if(!options.authMechanism) {
6560 options.authMechanism = 'MONGODB-CR';
6570 } else if(options.authMechanism != 'GSSAPI'
658 && options.authMechanism != 'MONGODB-CR'
659 && options.authMechanism != 'MONGODB-X509'
660 && options.authMechanism != 'PLAIN') {
6610 return callback(new Error("only GSSAPI, PLAIN, MONGODB-X509 or MONGODB-CR is supported by authMechanism"));
662 }
663
664 // the default db to authenticate against is 'this'
665 // if authententicate is called from a retry context, it may be another one, like admin
6660 var authdb = options.authdb ? options.authdb : self.databaseName;
6670 authdb = options.authSource ? options.authSource : authdb;
668
669 // Callback
6700 var _callback = function(err, result) {
6710 if(self.listeners("authenticated").length > 9) {
6720 self.emit("authenticated", err, result);
673 }
674
675 // Return to caller
6760 callback(err, result);
677 }
678
679 // If classic auth delegate to auth command
6800 if(options.authMechanism == 'MONGODB-CR') {
6810 mongodb_cr_authenticate(self, username, password, authdb, options, _callback);
6820 } else if(options.authMechanism == 'PLAIN') {
6830 mongodb_plain_authenticate(self, username, password, options, _callback);
6840 } else if(options.authMechanism == 'MONGODB-X509') {
6850 mongodb_x509_authenticate(self, username, password, options, _callback);
6860 } else if(options.authMechanism == 'GSSAPI') {
687 //
688 // Kerberos library is not installed, throw and error
6890 if(hasKerberos == false) {
6900 console.log("========================================================================================");
6910 console.log("= Please make sure that you install the Kerberos library to use GSSAPI =");
6920 console.log("= =");
6930 console.log("= npm install -g kerberos =");
6940 console.log("= =");
6950 console.log("= The Kerberos package is not installed by default for simplicities sake =");
6960 console.log("= and needs to be global install =");
6970 console.log("========================================================================================");
6980 throw new Error("Kerberos library not installed");
699 }
700
7010 if(process.platform == 'win32') {
7020 mongodb_sspi_authenticate(self, username, password, authdb, options, _callback);
703 } else {
704 // We have the kerberos library, execute auth process
7050 mongodb_gssapi_authenticate(self, username, password, authdb, options, _callback);
706 }
707 }
708};
709
710/**
711 * Add a user to the database.
712 *
713 * Options
714 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
715 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
716 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
717 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
718 * - **customData**, (Object, default:{}) custom data associated with the user (only Mongodb 2.6 or higher)
719 * - **roles**, (Array, default:[]) roles associated with the created user (only Mongodb 2.6 or higher)
720 *
721 * Deprecated Options
722 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
723 *
724 * @param {String} username username.
725 * @param {String} password password.
726 * @param {Object} [options] additional options during update.
727 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from addUser or null if an error occurred.
728 * @return {null}
729 * @api public
730 */
7311Db.prototype.addUser = function(username, password, options, callback) {
732 // Checkout a write connection to get the server capabilities
7330 var connection = this.serverConfig.checkoutWriter();
7340 if(connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasAuthCommands) {
7350 return _executeAuthCreateUserCommand(this, username, password, options, callback);
736 }
737
738 // Unpack the parameters
7390 var self = this;
7400 var args = Array.prototype.slice.call(arguments, 2);
7410 callback = args.pop();
7420 options = args.length ? args.shift() || {} : {};
743
744 // Get the error options
7450 var errorOptions = _getWriteConcern(this, options);
7460 errorOptions.w = errorOptions.w == null ? 1 : errorOptions.w;
747 // Use node md5 generator
7480 var md5 = crypto.createHash('md5');
749 // Generate keys used for authentication
7500 md5.update(username + ":mongo:" + password);
7510 var userPassword = md5.digest('hex');
752 // Fetch a user collection
7530 var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION);
754 // Check if we are inserting the first user
7550 collection.count({}, function(err, count) {
756 // We got an error (f.ex not authorized)
7570 if(err != null) return callback(err, null);
758 // Check if the user exists and update i
7590 collection.find({user: username}, {dbName: options['dbName']}).toArray(function(err, documents) {
760 // We got an error (f.ex not authorized)
7610 if(err != null) return callback(err, null);
762 // Add command keys
7630 var commandOptions = errorOptions;
7640 commandOptions.dbName = options['dbName'];
7650 commandOptions.upsert = true;
766
767 // We have a user, let's update the password or upsert if not
7680 collection.update({user: username},{$set: {user: username, pwd: userPassword}}, commandOptions, function(err, results, full) {
7690 if(count == 0 && err) {
7700 callback(null, [{user:username, pwd:userPassword}]);
7710 } else if(err) {
7720 callback(err, null)
773 } else {
7740 callback(null, [{user:username, pwd:userPassword}]);
775 }
776 });
777 });
778 });
779};
780
781/**
782 * @ignore
783 */
7841var _executeAuthCreateUserCommand = function(self, username, password, options, callback) {
785 // Special case where there is no password ($external users)
7860 if(typeof username == 'string'
787 && password != null && typeof password == 'object') {
7880 callback = options;
7890 options = password;
7900 password = null;
791 }
792
793 // Unpack all options
7940 if(typeof options == 'function') {
7950 callback = options;
7960 options = {};
797 }
798
799 // Error out if we digestPassword set
8000 if(options.digestPassword != null) {
8010 throw utils.toError("The digestPassword option is not supported via add_user. Please use db.command('createUser', ...) instead for this option.");
802 }
803
804 // Get additional values
8050 var customData = options.customData != null ? options.customData : {};
8060 var roles = Array.isArray(options.roles) ? options.roles : [];
8070 var maxTimeMS = typeof options.maxTimeMS == 'number' ? options.maxTimeMS : null;
808
809 // If not roles defined print deprecated message
8100 if(roles.length == 0) {
8110 console.log("Creating a user without roles is deprecated in MongoDB >= 2.6");
812 }
813
814 // Get the error options
8150 var writeConcern = _getWriteConcern(self, options);
8160 var commandOptions = {writeCommand:true};
8170 if(options['dbName']) commandOptions.dbName = options['dbName'];
818
819 // Add maxTimeMS to options if set
8200 if(maxTimeMS != null) commandOptions.maxTimeMS = maxTimeMS;
821
822 // Check the db name and add roles if needed
8230 if((self.databaseName.toLowerCase() == 'admin' || options.dbName == 'admin') && !Array.isArray(options.roles)) {
8240 roles = ['root']
8250 } else if(!Array.isArray(options.roles)) {
8260 roles = ['dbOwner']
827 }
828
829 // Build the command to execute
8300 var command = {
831 createUser: username
832 , customData: customData
833 , roles: roles
834 , digestPassword:false
835 , writeConcern: writeConcern
836 }
837
838 // Use node md5 generator
8390 var md5 = crypto.createHash('md5');
840 // Generate keys used for authentication
8410 md5.update(username + ":mongo:" + password);
8420 var userPassword = md5.digest('hex');
843
844 // No password
8450 if(typeof password == 'string') {
8460 command.pwd = userPassword;
847 }
848
849 // console.log("================================== add user")
850 // console.dir(command)
851
852 // Execute the command
8530 self.command(command, commandOptions, function(err, result) {
8540 if(err) return callback(err, null);
8550 callback(!result.ok ? utils.toError("Failed to add user " + username) : null
856 , result.ok ? [{user: username, pwd: ''}] : null);
857 })
858}
859
860/**
861 * Remove a user from a database
862 *
863 * Options
864 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
865 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
866 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
867 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
868 *
869 * Deprecated Options
870 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
871 *
872 * @param {String} username username.
873 * @param {Object} [options] additional options during update.
874 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occurred.
875 * @return {null}
876 * @api public
877 */
8781Db.prototype.removeUser = function(username, options, callback) {
879 // Checkout a write connection to get the server capabilities
8800 var connection = this.serverConfig.checkoutWriter();
8810 if(connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasAuthCommands) {
8820 return _executeAuthRemoveUserCommand(this, username, options, callback);
883 }
884
885 // Unpack the parameters
8860 var self = this;
8870 var args = Array.prototype.slice.call(arguments, 1);
8880 callback = args.pop();
8890 options = args.length ? args.shift() || {} : {};
890
891 // Figure out the safe mode settings
8920 var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe;
893 // Override with options passed in if applicable
8940 safe = options != null && options['safe'] != null ? options['safe'] : safe;
895 // Ensure it's at least set to safe
8960 safe = safe == null ? {w: 1} : safe;
897
898 // Fetch a user collection
8990 var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION);
9000 collection.findOne({user: username}, {dbName: options['dbName']}, function(err, user) {
9010 if(user != null) {
902 // Add command keys
9030 var commandOptions = safe;
9040 commandOptions.dbName = options['dbName'];
905
9060 collection.remove({user: username}, commandOptions, function(err, result) {
9070 callback(err, true);
908 });
909 } else {
9100 callback(err, false);
911 }
912 });
913};
914
9151var _executeAuthRemoveUserCommand = function(self, username, options, callback) {
916 // Unpack all options
9170 if(typeof options == 'function') {
9180 callback = options;
9190 options = {};
920 }
921
922 // Get the error options
9230 var writeConcern = _getWriteConcern(self, options);
9240 var commandOptions = {writeCommand:true};
9250 if(options['dbName']) commandOptions.dbName = options['dbName'];
926
927 // Get additional values
9280 var maxTimeMS = typeof options.maxTimeMS == 'number' ? options.maxTimeMS : null;
929
930 // Add maxTimeMS to options if set
9310 if(maxTimeMS != null) commandOptions.maxTimeMS = maxTimeMS;
932
933 // Build the command to execute
9340 var command = {
935 dropUser: username
936 , writeConcern: writeConcern
937 }
938
939 // Execute the command
9400 self.command(command, commandOptions, function(err, result) {
9410 if(err) return callback(err, null);
9420 callback(null, result.ok ? true : false);
943 })
944}
945
946/**
947 * Creates a collection on a server pre-allocating space, need to create f.ex capped collections.
948 *
949 * Options
950* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
951 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
952 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
953 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
954 * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document.
955 * - **raw** {Boolean, default:false}, perform all operations using raw bson objects.
956 * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
957 * - **capped** {Boolean, default:false}, create a capped collection.
958 * - **size** {Number}, the size of the capped collection in bytes.
959 * - **max** {Number}, the maximum number of documents in the capped collection.
960 * - **autoIndexId** {Boolean, default:true}, create an index on the _id field of the document, True by default on MongoDB 2.2 or higher off for version < 2.2.
961 * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
962 * - **strict**, (Boolean, default:false) throws an error if collection already exists
963 *
964 * Deprecated Options
965 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
966 *
967 * @param {String} collectionName the collection name we wish to access.
968 * @param {Object} [options] returns option results.
969 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from createCollection or null if an error occurred.
970 * @return {null}
971 * @api public
972 */
9731Db.prototype.createCollection = function(collectionName, options, callback) {
9740 var self = this;
9750 if(typeof options == 'function') {
9760 callback = options;
9770 options = {};
978 }
979
980 // Figure out the safe mode settings
9810 var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe;
982 // Override with options passed in if applicable
9830 safe = options != null && options['safe'] != null ? options['safe'] : safe;
984 // Ensure it's at least set to safe
9850 safe = safe == null ? {w: 1} : safe;
986
987 // Check if we have the name
9880 this.collectionNames(collectionName, function(err, collections) {
9890 if(err != null) return callback(err, null);
990
9910 var found = false;
9920 collections.forEach(function(collection) {
9930 if(collection.name == self.databaseName + "." + collectionName) found = true;
994 });
995
996 // If the collection exists either throw an exception (if db in safe mode) or return the existing collection
9970 if(found && options && options.strict) {
9980 return callback(new Error("Collection " + collectionName + " already exists. Currently in safe mode."), null);
9990 } else if(found){
10000 try {
10010 var collection = new Collection(self, collectionName, self.pkFactory, options);
1002 } catch(err) {
10030 return callback(err, null);
1004 }
10050 return callback(null, collection);
1006 }
1007
1008 // Create a new collection and return it
10090 self._executeQueryCommand(DbCommand.createCreateCollectionCommand(self, collectionName, options)
1010 , {read:false, safe:safe}
1011 , utils.handleSingleCommandResultReturn(null, null, function(err, result) {
10120 if(err) return callback(err, null);
1013 // Create collection and return
10140 try {
10150 return callback(null, new Collection(self, collectionName, self.pkFactory, options));
1016 } catch(err) {
10170 return callback(err, null);
1018 }
1019 }));
1020 });
1021};
1022
10231var _getReadConcern = function(self, options) {
10240 if(options.readPreference) return options.readPreference;
10250 if(self.readPreference) return self.readPreference;
10260 return 'primary';
1027}
1028
1029/**
1030 * Execute a command hash against MongoDB. This lets you acess any commands not available through the api on the server.
1031 *
1032 * Options
1033 * - **maxTimeMS** {Number}, number of miliseconds to wait before aborting the query.
1034 * - **ignoreCommandFilter** {Boolean}, overrides the default redirection of certain commands to primary.
1035 * - **writeCommand** {Boolean, default: false}, signals this is a write command and to ignore read preferences
1036 * - **checkKeys** {Boolean, default: false}, overrides the default not to check the key names for the command
1037 *
1038 * @param {Object} selector the command hash to send to the server, ex: {ping:1}.
1039 * @param {Object} [options] additional options for the command.
1040 * @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter.
1041 * @return {null}
1042 * @api public
1043 */
10441Db.prototype.command = function(selector, options, callback) {
10450 if(typeof options == 'function') {
10460 callback = options;
10470 options = {};
1048 }
1049
1050 // Ignore command preference (I know what I'm doing)
10510 var ignoreCommandFilter = options.ignoreCommandFilter ? options.ignoreCommandFilter : false;
1052 // Set read preference if we set one
10530 var readPreference = _getReadConcern(this, options);
1054
1055 // Ensure only commands who support read Prefrences are exeuted otherwise override and use Primary
10560 if(readPreference != false && ignoreCommandFilter == false) {
10570 if(selector['group'] || selector['aggregate'] || selector['collStats'] || selector['dbStats']
1058 || selector['count'] || selector['distinct'] || selector['geoNear'] || selector['geoSearch']
1059 || selector['geoWalk'] || selector['text']
1060 || (selector['mapreduce'] && (selector.out == 'inline' || selector.out.inline))) {
1061 // Set the read preference
10620 options.readPreference = readPreference;
1063 } else {
10640 options.readPreference = ReadPreference.PRIMARY;
1065 }
10660 } else if(readPreference != false) {
10670 options.readPreference = readPreference;
1068 }
1069
1070 // Add the maxTimeMS option to the command if specified
10710 if(typeof options.maxTimeMS == 'number') {
10720 selector.maxTimeMS = options.maxTimeMS
1073 }
1074
1075 // Command options
10760 var command_options = {};
1077
1078 // Do we have an override for checkKeys
10790 if(typeof options['checkKeys'] == 'boolean') command_options['checkKeys'] = options['checkKeys'];
10800 command_options['checkKeys'] = typeof options['checkKeys'] == 'boolean' ? options['checkKeys'] : false;
10810 if(typeof options['serializeFunctions'] == 'boolean') command_options['serializeFunctions'] = options['serializeFunctions'];
10820 if(options['dbName']) command_options['dbName'] = options['dbName'];
1083
1084 // If we have a write command, remove readPreference as an option
10850 if((options.writeCommand
1086 || selector['findAndModify']
1087 || selector['insert'] || selector['update'] || selector['delete']
1088 || selector['createUser'] || selector['updateUser'] || selector['removeUser'])
1089 && options.readPreference) {
10900 delete options['readPreference'];
1091 }
1092
1093 // Execute a query command
10940 this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, selector, command_options), options, function(err, results) {
10950 if(err) return callback(err, null);
10960 if(results.documents[0].errmsg)
10970 return callback(utils.toError(results.documents[0]), null);
10980 callback(null, results.documents[0]);
1099 });
1100};
1101
1102/**
1103 * Drop a collection from the database, removing it permanently. New accesses will create a new collection.
1104 *
1105 * @param {String} collectionName the name of the collection we wish to drop.
1106 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropCollection or null if an error occurred.
1107 * @return {null}
1108 * @api public
1109 */
11101Db.prototype.dropCollection = function(collectionName, callback) {
11110 var self = this;
11120 callback || (callback = function(){});
1113
1114 // Drop the collection
11150 this._executeQueryCommand(DbCommand.createDropCollectionCommand(this, collectionName)
1116 , utils.handleSingleCommandResultReturn(true, false, callback)
1117 );
1118};
1119
1120/**
1121 * Rename a collection.
1122 *
1123 * Options
1124 * - **dropTarget** {Boolean, default:false}, drop the target name collection if it previously exists.
1125 *
1126 * @param {String} fromCollection the name of the current collection we wish to rename.
1127 * @param {String} toCollection the new name of the collection.
1128 * @param {Object} [options] returns option results.
1129 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from renameCollection or null if an error occurred.
1130 * @return {null}
1131 * @api public
1132 */
11331Db.prototype.renameCollection = function(fromCollection, toCollection, options, callback) {
11340 var self = this;
1135
11360 if(typeof options == 'function') {
11370 callback = options;
11380 options = {}
1139 }
1140
1141 // Add return new collection
11420 options.new_collection = true;
1143
1144 // Execute using the collection method
11450 this.collection(fromCollection).rename(toCollection, options, callback);
1146};
1147
1148/**
1149 * Return last error message for the given connection, note options can be combined.
1150 *
1151 * Options
1152 * - **fsync** {Boolean, default:false}, option forces the database to fsync all files before returning.
1153 * - **j** {Boolean, default:false}, awaits the journal commit before returning, > MongoDB 2.0.
1154 * - **w** {Number}, until a write operation has been replicated to N servers.
1155 * - **wtimeout** {Number}, number of miliseconds to wait before timing out.
1156 *
1157 * Connection Options
1158 * - **connection** {Connection}, fire the getLastError down a specific connection.
1159 *
1160 * @param {Object} [options] returns option results.
1161 * @param {Object} [connectionOptions] returns option results.
1162 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from lastError or null if an error occurred.
1163 * @return {null}
1164 * @api public
1165 */
11661Db.prototype.lastError = function(options, connectionOptions, callback) {
1167 // Unpack calls
11680 var args = Array.prototype.slice.call(arguments, 0);
11690 callback = args.pop();
11700 options = args.length ? args.shift() || {} : {};
11710 connectionOptions = args.length ? args.shift() || {} : {};
1172
11730 this._executeQueryCommand(DbCommand.createGetLastErrorCommand(options, this), connectionOptions, function(err, error) {
11740 callback(err, error && error.documents);
1175 });
1176};
1177
1178/**
1179 * Legacy method calls.
1180 *
1181 * @ignore
1182 * @api private
1183 */
11841Db.prototype.error = Db.prototype.lastError;
11851Db.prototype.lastStatus = Db.prototype.lastError;
1186
1187/**
1188 * Return all errors up to the last time db reset_error_history was called.
1189 *
1190 * Options
1191 * - **connection** {Connection}, fire the getLastError down a specific connection.
1192 *
1193 * @param {Object} [options] returns option results.
1194 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from previousErrors or null if an error occurred.
1195 * @return {null}
1196 * @api public
1197 */
11981Db.prototype.previousErrors = function(options, callback) {
1199 // Unpack calls
12000 var args = Array.prototype.slice.call(arguments, 0);
12010 callback = args.pop();
12020 options = args.length ? args.shift() || {} : {};
1203
12040 this._executeQueryCommand(DbCommand.createGetPreviousErrorsCommand(this), options, function(err, error) {
12050 callback(err, error.documents);
1206 });
1207};
1208
1209/**
1210 * Runs a command on the database.
1211 * @ignore
1212 * @api private
1213 */
12141Db.prototype.executeDbCommand = function(command_hash, options, callback) {
12150 if(callback == null) { callback = options; options = {}; }
12160 this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, command_hash, options), options, function(err, result) {
12170 if(callback) callback(err, result);
1218 });
1219};
1220
1221/**
1222 * Runs a command on the database as admin.
1223 * @ignore
1224 * @api private
1225 */
12261Db.prototype.executeDbAdminCommand = function(command_hash, options, callback) {
12270 if(typeof options == 'function') {
12280 callback = options;
12290 options = {}
1230 }
1231
12320 if(options.readPreference) {
12330 options.read = options.readPreference;
1234 }
1235
12360 this._executeQueryCommand(DbCommand.createAdminDbCommand(this, command_hash), options, function(err, result) {
12370 if(callback) callback(err, result);
1238 });
1239};
1240
1241/**
1242 * Resets the error history of the mongo instance.
1243 *
1244 * Options
1245 * - **connection** {Connection}, fire the getLastError down a specific connection.
1246 *
1247 * @param {Object} [options] returns option results.
1248 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from resetErrorHistory or null if an error occurred.
1249 * @return {null}
1250 * @api public
1251 */
12521Db.prototype.resetErrorHistory = function(options, callback) {
1253 // Unpack calls
12540 var args = Array.prototype.slice.call(arguments, 0);
12550 callback = args.pop();
12560 options = args.length ? args.shift() || {} : {};
1257
12580 this._executeQueryCommand(DbCommand.createResetErrorHistoryCommand(this), options, function(err, error) {
12590 if(callback) callback(err, error && error.documents);
1260 });
1261};
1262
1263/**
1264 * Creates an index on the collection.
1265 *
1266 * Options
1267* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
1268 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
1269 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
1270 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
1271 * - **unique** {Boolean, default:false}, creates an unique index.
1272 * - **sparse** {Boolean, default:false}, creates a sparse index.
1273 * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible.
1274 * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value
1275 * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates.
1276 * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates.
1277 * - **v** {Number}, specify the format version of the indexes.
1278 * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
1279 * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
1280 *
1281 * Deprecated Options
1282 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
1283 *
1284 *
1285 * @param {String} collectionName name of the collection to create the index on.
1286 * @param {Object} fieldOrSpec fieldOrSpec that defines the index.
1287 * @param {Object} [options] additional options during update.
1288 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from createIndex or null if an error occurred.
1289 * @return {null}
1290 * @api public
1291 */
12921Db.prototype.createIndex = function(collectionName, fieldOrSpec, options, callback) {
12930 var self = this;
12940 var args = Array.prototype.slice.call(arguments, 2);
12950 callback = args.pop();
12960 options = args.length ? args.shift() || {} : {};
12970 options = typeof callback === 'function' ? options : callback;
12980 options = options == null ? {} : options;
1299
1300 // Get the error options
13010 var errorOptions = _getWriteConcern(this, options);
1302 // Create command
13030 var command = DbCommand.createCreateIndexCommand(this, collectionName, fieldOrSpec, options);
1304 // Default command options
13050 var commandOptions = {};
1306
1307 // If we have error conditions set handle them
13080 if(_hasWriteConcern(errorOptions) && typeof callback == 'function') {
1309 // Insert options
13100 commandOptions['read'] = false;
1311 // If we have safe set set async to false
13120 if(errorOptions == null) commandOptions['async'] = true;
1313
1314 // Set safe option
13150 commandOptions['safe'] = errorOptions;
1316 // If we have an error option
13170 if(typeof errorOptions == 'object') {
13180 var keys = Object.keys(errorOptions);
13190 for(var i = 0; i < keys.length; i++) {
13200 commandOptions[keys[i]] = errorOptions[keys[i]];
1321 }
1322 }
1323
1324 // Execute insert command
13250 this._executeInsertCommand(command, commandOptions, function(err, result) {
13260 if(err != null) return callback(err, null);
1327
13280 result = result && result.documents;
13290 if (result[0].err) {
13300 callback(utils.toError(result[0]));
1331 } else {
13320 callback(null, command.documents[0].name);
1333 }
1334 });
13350 } else if(_hasWriteConcern(errorOptions) && callback == null) {
13360 throw new Error("Cannot use a writeConcern without a provided callback");
1337 } else {
1338 // Execute insert command
13390 var result = this._executeInsertCommand(command, commandOptions);
1340 // If no callback just return
13410 if(!callback) return;
1342 // If error return error
13430 if(result instanceof Error) {
13440 return callback(result);
1345 }
1346 // Otherwise just return
13470 return callback(null, null);
1348 }
1349};
1350
1351/**
1352 * Ensures that an index exists, if it does not it creates it
1353 *
1354 * Options
1355 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write
1356 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
1357 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
1358 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
1359 * - **unique** {Boolean, default:false}, creates an unique index.
1360 * - **sparse** {Boolean, default:false}, creates a sparse index.
1361 * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible.
1362 * - **dropDups** {Boolean, default:false}, a unique index cannot be created on a key that has pre-existing duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate value
1363 * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates.
1364 * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates.
1365 * - **v** {Number}, specify the format version of the indexes.
1366 * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher)
1367 * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes)
1368 *
1369 * Deprecated Options
1370 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
1371 *
1372 * @param {String} collectionName name of the collection to create the index on.
1373 * @param {Object} fieldOrSpec fieldOrSpec that defines the index.
1374 * @param {Object} [options] additional options during update.
1375 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from ensureIndex or null if an error occurred.
1376 * @return {null}
1377 * @api public
1378 */
13791Db.prototype.ensureIndex = function(collectionName, fieldOrSpec, options, callback) {
13800 var self = this;
1381
13820 if (typeof callback === 'undefined' && typeof options === 'function') {
13830 callback = options;
13840 options = {};
1385 }
1386
13870 if (options == null) {
13880 options = {};
1389 }
1390
1391 // Get the error options
13920 var errorOptions = _getWriteConcern(this, options);
1393 // Make sure we don't try to do a write concern without a callback
13940 if(_hasWriteConcern(errorOptions) && callback == null)
13950 throw new Error("Cannot use a writeConcern without a provided callback");
1396 // Create command
13970 var command = DbCommand.createCreateIndexCommand(this, collectionName, fieldOrSpec, options);
13980 var index_name = command.documents[0].name;
1399
1400 // Default command options
14010 var commandOptions = {};
1402 // Check if the index allready exists
14030 this.indexInformation(collectionName, function(err, collectionInfo) {
14040 if(err != null) return callback(err, null);
1405
14060 if(!collectionInfo[index_name]) {
1407 // If we have error conditions set handle them
14080 if(_hasWriteConcern(errorOptions) && typeof callback == 'function') {
1409 // Insert options
14100 commandOptions['read'] = false;
1411 // If we have safe set set async to false
14120 if(errorOptions == null) commandOptions['async'] = true;
1413
1414 // If we have an error option
14150 if(typeof errorOptions == 'object') {
14160 var keys = Object.keys(errorOptions);
14170 for(var i = 0; i < keys.length; i++) {
14180 commandOptions[keys[i]] = errorOptions[keys[i]];
1419 }
1420 }
1421
14220 if(typeof callback === 'function'
1423 && commandOptions.w < 1 && !commandOptions.fsync && !commandOptions.journal) {
14240 commandOptions.w = 1;
1425 }
1426
14270 self._executeInsertCommand(command, commandOptions, function(err, result) {
1428 // Only callback if we have one specified
14290 if(typeof callback === 'function') {
14300 if(err != null) return callback(err, null);
1431
14320 result = result && result.documents;
14330 if (result[0].err) {
14340 callback(utils.toError(result[0]));
1435 } else {
14360 callback(null, command.documents[0].name);
1437 }
1438 }
1439 });
1440 } else {
1441 // Execute insert command
14420 var result = self._executeInsertCommand(command, commandOptions);
1443 // If no callback just return
14440 if(!callback) return;
1445 // If error return error
14460 if(result instanceof Error) {
14470 return callback(result);
1448 }
1449 // Otherwise just return
14500 return callback(null, index_name);
1451 }
1452 } else {
14530 if(typeof callback === 'function') return callback(null, index_name);
1454 }
1455 });
1456};
1457
1458/**
1459 * Returns the information available on allocated cursors.
1460 *
1461 * Options
1462 * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
1463 *
1464 * @param {Object} [options] additional options during update.
1465 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from cursorInfo or null if an error occurred.
1466 * @return {null}
1467 * @api public
1468 */
14691Db.prototype.cursorInfo = function(options, callback) {
14700 var args = Array.prototype.slice.call(arguments, 0);
14710 callback = args.pop();
14720 options = args.length ? args.shift() || {} : {};
1473
14740 this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, {'cursorInfo':1})
1475 , options
1476 , utils.handleSingleCommandResultReturn(null, null, callback));
1477};
1478
1479/**
1480 * Drop an index on a collection.
1481 *
1482 * @param {String} collectionName the name of the collection where the command will drop an index.
1483 * @param {String} indexName name of the index to drop.
1484 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropIndex or null if an error occurred.
1485 * @return {null}
1486 * @api public
1487 */
14881Db.prototype.dropIndex = function(collectionName, indexName, callback) {
14890 this._executeQueryCommand(DbCommand.createDropIndexCommand(this, collectionName, indexName)
1490 , utils.handleSingleCommandResultReturn(null, null, callback));
1491};
1492
1493/**
1494 * Reindex all indexes on the collection
1495 * Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections.
1496 *
1497 * @param {String} collectionName the name of the collection.
1498 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from reIndex or null if an error occurred.
1499 * @api public
1500**/
15011Db.prototype.reIndex = function(collectionName, callback) {
15020 this._executeQueryCommand(DbCommand.createReIndexCommand(this, collectionName)
1503 , utils.handleSingleCommandResultReturn(true, false, callback));
1504};
1505
1506/**
1507 * Retrieves this collections index info.
1508 *
1509 * Options
1510 * - **full** {Boolean, default:false}, returns the full raw index information.
1511 * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST).
1512 *
1513 * @param {String} collectionName the name of the collection.
1514 * @param {Object} [options] additional options during update.
1515 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from indexInformation or null if an error occurred.
1516 * @return {null}
1517 * @api public
1518 */
15191Db.prototype.indexInformation = function(collectionName, options, callback) {
15200 if(typeof callback === 'undefined') {
15210 if(typeof options === 'undefined') {
15220 callback = collectionName;
15230 collectionName = null;
1524 } else {
15250 callback = options;
1526 }
15270 options = {};
1528 }
1529
1530 // If we specified full information
15310 var full = options['full'] == null ? false : options['full'];
1532 // Build selector for the indexes
15330 var selector = collectionName != null ? {ns: (this.databaseName + "." + collectionName)} : {};
1534
1535 // Set read preference if we set one
15360 var readPreference = options['readPreference'] ? options['readPreference'] : ReadPreference.PRIMARY;
1537
1538 // Iterate through all the fields of the index
15390 this.collection(DbCommand.SYSTEM_INDEX_COLLECTION, function(err, collection) {
1540 // Perform the find for the collection
15410 collection.find(selector).setReadPreference(readPreference).toArray(function(err, indexes) {
15420 if(err != null) return callback(err, null);
1543 // Contains all the information
15440 var info = {};
1545
1546 // if full defined just return all the indexes directly
15470 if(full) return callback(null, indexes);
1548
1549 // Process all the indexes
15500 for(var i = 0; i < indexes.length; i++) {
15510 var index = indexes[i];
1552 // Let's unpack the object
15530 info[index.name] = [];
15540 for(var name in index.key) {
15550 info[index.name].push([name, index.key[name]]);
1556 }
1557 }
1558
1559 // Return all the indexes
15600 callback(null, info);
1561 });
1562 });
1563};
1564
1565/**
1566 * Drop a database.
1567 *
1568 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropDatabase or null if an error occurred.
1569 * @return {null}
1570 * @api public
1571 */
15721Db.prototype.dropDatabase = function(callback) {
15730 this._executeQueryCommand(DbCommand.createDropDatabaseCommand(this)
1574 , utils.handleSingleCommandResultReturn(true, false, callback));
1575}
1576
1577/**
1578 * Get all the db statistics.
1579 *
1580 * Options
1581 * - **scale** {Number}, divide the returned sizes by scale value.
1582 * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST).
1583 *
1584 * @param {Objects} [options] options for the stats command
1585 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from stats or null if an error occurred.
1586 * @return {null}
1587 * @api public
1588 */
15891Db.prototype.stats = function stats(options, callback) {
15900 var args = Array.prototype.slice.call(arguments, 0);
15910 callback = args.pop();
1592 // Fetch all commands
15930 options = args.length ? args.shift() || {} : {};
1594
1595 // Build command object
15960 var commandObject = {
1597 dbStats:this.collectionName
1598 };
1599
1600 // Check if we have the scale value
16010 if(options['scale'] != null) commandObject['scale'] = options['scale'];
1602
1603 // Execute the command
16040 this.command(commandObject, options, callback);
1605}
1606
1607/**
1608 * @ignore
1609 */
16101var __executeQueryCommand = function(self, db_command, options, callback) {
1611 // Options unpacking
16120 var read = options['read'] != null ? options['read'] : false;
16130 read = options['readPreference'] != null && options['read'] == null ? options['readPreference'] : read;
16140 var raw = options['raw'] != null ? options['raw'] : self.raw;
16150 var onAll = options['onAll'] != null ? options['onAll'] : false;
16160 var specifiedConnection = options['connection'] != null ? options['connection'] : null;
1617
1618 // Correct read preference to default primary if set to false, null or primary
16190 if(!(typeof read == 'object') && read._type == 'ReadPreference') {
16200 read = (read == null || read == 'primary' || read == false) ? ReadPreference.PRIMARY : read;
16210 if(!ReadPreference.isValid(read)) return callback(new Error("Illegal readPreference mode specified, " + read));
16220 } else if(typeof read == 'object' && read._type == 'ReadPreference') {
16230 if(!read.isValid()) return callback(new Error("Illegal readPreference mode specified, " + read.mode));
1624 }
1625
1626 // If we have a read preference set and we are a mongos pass the read preference on to the mongos instance,
16270 if(self.serverConfig.isMongos() && read != null && read != false) {
16280 db_command.setMongosReadPreference(read);
1629 }
1630
1631 // If we got a callback object
16320 if(typeof callback === 'function' && !onAll) {
1633 // Override connection if we passed in a specific connection
16340 var connection = specifiedConnection != null ? specifiedConnection : null;
1635
16360 if(connection instanceof Error) return callback(connection, null);
1637
1638 // Fetch either a reader or writer dependent on the specified read option if no connection
1639 // was passed in
16400 if(connection == null) {
16410 connection = self.serverConfig.checkoutReader(read);
1642 }
1643
16440 if(connection == null) {
16450 return callback(new Error("no open connections"));
16460 } else if(connection instanceof Error || connection['message'] != null) {
16470 return callback(connection);
1648 }
1649
1650 // Exhaust Option
16510 var exhaust = options.exhaust || false;
1652
1653 // Register the handler in the data structure
16540 self.serverConfig._registerHandler(db_command, raw, connection, exhaust, callback);
1655
1656 // Write the message out and handle any errors if there are any
16570 connection.write(db_command, function(err) {
16580 if(err != null) {
1659 // Call the handler with an error
16600 if(Array.isArray(db_command))
16610 self.serverConfig._callHandler(db_command[0].getRequestId(), null, err);
1662 else
16630 self.serverConfig._callHandler(db_command.getRequestId(), null, err);
1664 }
1665 });
16660 } else if(typeof callback === 'function' && onAll) {
16670 var connections = self.serverConfig.allRawConnections();
16680 var numberOfEntries = connections.length;
1669 // Go through all the connections
16700 for(var i = 0; i < connections.length; i++) {
1671 // Fetch a connection
16720 var connection = connections[i];
1673
1674 // Ensure we have a valid connection
16750 if(connection == null) {
16760 return callback(new Error("no open connections"));
16770 } else if(connection instanceof Error) {
16780 return callback(connection);
1679 }
1680
1681 // Register the handler in the data structure
16820 self.serverConfig._registerHandler(db_command, raw, connection, callback);
1683
1684 // Write the message out
16850 connection.write(db_command, function(err) {
1686 // Adjust the number of entries we need to process
16870 numberOfEntries = numberOfEntries - 1;
1688 // Remove listener
16890 if(err != null) {
1690 // Clean up listener and return error
16910 self.serverConfig._removeHandler(db_command.getRequestId());
1692 }
1693
1694 // No more entries to process callback with the error
16950 if(numberOfEntries <= 0) {
16960 callback(err);
1697 }
1698 });
1699
1700 // Update the db_command request id
17010 db_command.updateRequestId();
1702 }
1703 } else {
1704 // Fetch either a reader or writer dependent on the specified read option
1705 // var connection = read == null || read == 'primary' || read == false ? self.serverConfig.checkoutWriter(true) : self.serverConfig.checkoutReader(read);
17060 var connection = self.serverConfig.checkoutReader(read);
1707 // Override connection if needed
17080 connection = specifiedConnection != null ? specifiedConnection : connection;
1709 // Ensure we have a valid connection
17100 if(connection == null || connection instanceof Error || connection['message'] != null) return null;
1711 // Write the message out
17120 connection.write(db_command, function(err) {
17130 if(err != null) {
1714 // Emit the error
17150 self.emit("error", err);
1716 }
1717 });
1718 }
1719};
1720
1721/**
1722 * Execute db query command (not safe)
1723 * @ignore
1724 * @api private
1725 */
17261Db.prototype._executeQueryCommand = function(db_command, options, callback) {
17270 var self = this;
1728
1729 // Unpack the parameters
17300 if (typeof callback === 'undefined') {
17310 callback = options;
17320 options = {};
1733 }
1734
1735 // fast fail option used for HA, no retry
17360 var failFast = options['failFast'] != null
1737 ? options['failFast']
1738 : false;
1739
1740 // Check if the user force closed the command
17410 if(this._applicationClosed) {
17420 var err = new Error("db closed by application");
17430 if('function' == typeof callback) {
17440 return callback(err, null);
1745 } else {
17460 throw err;
1747 }
1748 }
1749
17500 if(this.serverConfig.isDestroyed())
17510 return callback(new Error("Connection was destroyed by application"));
1752
1753 // Specific connection
17540 var connection = options.connection;
1755 // Check if the connection is actually live
17560 if(connection
17570 && (!connection.isConnected || !connection.isConnected())) connection = null;
1758
1759 // Get the configuration
17600 var config = this.serverConfig;
17610 var read = options.read;
1762 // Allow for the usage of the readPreference model
17630 if(read == null) {
17640 read = options.readPreference;
1765 }
1766
17670 if(!connection && !config.canRead(read) && !config.canWrite() && config.isAutoReconnect()) {
17680 if(read == ReadPreference.PRIMARY
1769 || read == ReadPreference.PRIMARY_PREFERRED
1770 || (read != null && typeof read == 'object' && read.mode)
1771 || read == null) {
1772
1773 // Save the command
17740 self.serverConfig._commandsStore.read_from_writer(
1775 { type: 'query'
1776 , db_command: db_command
1777 , options: options
1778 , callback: callback
1779 , db: self
1780 , executeQueryCommand: __executeQueryCommand
1781 , executeInsertCommand: __executeInsertCommand
1782 }
1783 );
1784 } else {
17850 self.serverConfig._commandsStore.read(
1786 { type: 'query'
1787 , db_command: db_command
1788 , options: options
1789 , callback: callback
1790 , db: self
1791 , executeQueryCommand: __executeQueryCommand
1792 , executeInsertCommand: __executeInsertCommand
1793 }
1794 );
1795 }
1796
1797 // If we have blown through the number of items let's
17980 if(!self.serverConfig._commandsStore.validateBufferLimit(self.bufferMaxEntries)) {
17990 self.close();
1800 }
18010 } else if(!connection && !config.canRead(read) && !config.canWrite() && !config.isAutoReconnect()) {
18020 return callback(new Error("no open connections"), null);
1803 } else {
18040 if(typeof callback == 'function') {
18050 __executeQueryCommand(self, db_command, options, function (err, result, conn) {
18060 callback(err, result, conn);
1807 });
1808 } else {
18090 __executeQueryCommand(self, db_command, options);
1810 }
1811 }
1812};
1813
1814/**
1815 * @ignore
1816 */
18171var __executeInsertCommand = function(self, db_command, options, callback) {
1818 // Always checkout a writer for this kind of operations
18190 var connection = self.serverConfig.checkoutWriter();
1820 // Get safe mode
18210 var safe = options['safe'] != null ? options['safe'] : false;
18220 var raw = options['raw'] != null ? options['raw'] : self.raw;
18230 var specifiedConnection = options['connection'] != null ? options['connection'] : null;
1824 // Override connection if needed
18250 connection = specifiedConnection != null ? specifiedConnection : connection;
1826
1827 // Validate if we can use this server 2.6 wire protocol
18280 if(!connection.isCompatible()) {
18290 return callback(utils.toError("driver is incompatible with this server version"), null);
1830 }
1831
1832 // Ensure we have a valid connection
18330 if(typeof callback === 'function') {
1834 // Ensure we have a valid connection
18350 if(connection == null) {
18360 return callback(new Error("no open connections"));
18370 } else if(connection instanceof Error) {
18380 return callback(connection);
1839 }
1840
18410 var errorOptions = _getWriteConcern(self, options);
18420 if(errorOptions.w > 0 || errorOptions.w == 'majority' || errorOptions.j || errorOptions.journal || errorOptions.fsync) {
1843 // db command is now an array of commands (original command + lastError)
18440 db_command = [db_command, DbCommand.createGetLastErrorCommand(safe, self)];
1845 // Register the handler in the data structure
18460 self.serverConfig._registerHandler(db_command[1], raw, connection, callback);
1847 }
1848 }
1849
1850 // If we have no callback and there is no connection
18510 if(connection == null) return null;
18520 if(connection instanceof Error && typeof callback == 'function') return callback(connection, null);
18530 if(connection instanceof Error) return null;
18540 if(connection == null && typeof callback == 'function') return callback(new Error("no primary server found"), null);
1855
1856 // Write the message out
18570 connection.write(db_command, function(err) {
1858 // Return the callback if it's not a safe operation and the callback is defined
18590 if(typeof callback === 'function' && (safe == null || safe == false)) {
1860 // Perform the callback
18610 callback(err, null);
18620 } else if(typeof callback === 'function') {
1863 // Call the handler with an error
18640 self.serverConfig._callHandler(db_command[1].getRequestId(), null, err);
18650 } else if(typeof callback == 'function' && safe && safe.w == -1) {
1866 // Call the handler with no error
18670 self.serverConfig._callHandler(db_command[1].getRequestId(), null, null);
18680 } else if(!safe || safe.w == -1) {
18690 self.emit("error", err);
1870 }
1871 });
1872};
1873
1874/**
1875 * Execute an insert Command
1876 * @ignore
1877 * @api private
1878 */
18791Db.prototype._executeInsertCommand = function(db_command, options, callback) {
18800 var self = this;
1881
1882 // Unpack the parameters
18830 if(callback == null && typeof options === 'function') {
18840 callback = options;
18850 options = {};
1886 }
1887
1888 // Ensure options are not null
18890 options = options == null ? {} : options;
1890
1891 // Check if the user force closed the command
18920 if(this._applicationClosed) {
18930 if(typeof callback == 'function') {
18940 return callback(new Error("db closed by application"), null);
1895 } else {
18960 throw new Error("db closed by application");
1897 }
1898 }
1899
19000 if(this.serverConfig.isDestroyed()) return callback(new Error("Connection was destroyed by application"));
1901
1902 // Specific connection
19030 var connection = options.connection;
1904 // Check if the connection is actually live
19050 if(connection
19060 && (!connection.isConnected || !connection.isConnected())) connection = null;
1907
1908 // Get config
19090 var config = self.serverConfig;
1910 // Check if we are connected
19110 if(!connection && !config.canWrite() && config.isAutoReconnect()) {
19120 self.serverConfig._commandsStore.write(
1913 { type:'insert'
1914 , 'db_command':db_command
1915 , 'options':options
1916 , 'callback':callback
1917 , db: self
1918 , executeQueryCommand: __executeQueryCommand
1919 , executeInsertCommand: __executeInsertCommand
1920 }
1921 );
1922
1923 // If we have blown through the number of items let's
19240 if(!self.serverConfig._commandsStore.validateBufferLimit(self.bufferMaxEntries)) {
19250 self.close();
1926 }
19270 } else if(!connection && !config.canWrite() && !config.isAutoReconnect()) {
19280 return callback(new Error("no open connections"), null);
1929 } else {
19300 __executeInsertCommand(self, db_command, options, callback);
1931 }
1932};
1933
1934/**
1935 * Update command is the same
1936 * @ignore
1937 * @api private
1938 */
19391Db.prototype._executeUpdateCommand = Db.prototype._executeInsertCommand;
1940/**
1941 * Remove command is the same
1942 * @ignore
1943 * @api private
1944 */
19451Db.prototype._executeRemoveCommand = Db.prototype._executeInsertCommand;
1946
1947/**
1948 * Wrap a Mongo error document into an Error instance.
1949 * Deprecated. Use utils.toError instead.
1950 *
1951 * @ignore
1952 * @api private
1953 * @deprecated
1954 */
19551Db.prototype.wrap = utils.toError;
1956
1957/**
1958 * Default URL
1959 *
1960 * @classconstant DEFAULT_URL
1961 **/
19621Db.DEFAULT_URL = 'mongodb://localhost:27017/default';
1963
1964/**
1965 * Connect to MongoDB using a url as documented at
1966 *
1967 * docs.mongodb.org/manual/reference/connection-string/
1968 *
1969 * Options
1970 * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication
1971 * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor**
1972 * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor**
1973 * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor**
1974 * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor**
1975 *
1976 * @param {String} url connection url for MongoDB.
1977 * @param {Object} [options] optional options for insert command
1978 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the db instance or null if an error occurred.
1979 * @return {null}
1980 * @api public
1981 */
19821Db.connect = function(url, options, callback) {
1983 // Ensure correct mapping of the callback
19840 if(typeof options == 'function') {
19850 callback = options;
19860 options = {};
1987 }
1988
1989 // Ensure same behavior as previous version w:0
19900 if(url.indexOf("safe") == -1
1991 && url.indexOf("w") == -1
1992 && url.indexOf("journal") == -1 && url.indexOf("j") == -1
19930 && url.indexOf("fsync") == -1) options.w = 0;
1994
1995 // Avoid circular require problem
19960 var MongoClient = require('./mongo_client.js').MongoClient;
1997 // Attempt to connect
19980 MongoClient.connect.call(MongoClient, url, options, callback);
1999};
2000
2001/**
2002 * State of the db connection
2003 * @ignore
2004 */
20051Object.defineProperty(Db.prototype, "state", { enumerable: true
2006 , get: function () {
20070 return this.serverConfig._serverState;
2008 }
2009});
2010
2011/**
2012 * @ignore
2013 */
20141var _hasWriteConcern = function(errorOptions) {
20150 return errorOptions == true
2016 || errorOptions.w > 0
2017 || errorOptions.w == 'majority'
2018 || errorOptions.j == true
2019 || errorOptions.journal == true
2020 || errorOptions.fsync == true
2021};
2022
2023/**
2024 * @ignore
2025 */
20261var _setWriteConcernHash = function(options) {
20270 var finalOptions = {};
20280 if(options.w != null) finalOptions.w = options.w;
20290 if(options.journal == true) finalOptions.j = options.journal;
20300 if(options.j == true) finalOptions.j = options.j;
20310 if(options.fsync == true) finalOptions.fsync = options.fsync;
20320 if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout;
20330 return finalOptions;
2034};
2035
2036/**
2037 * @ignore
2038 */
20391var _getWriteConcern = function(self, options, callback) {
2040 // Final options
20410 var finalOptions = {w:1};
2042 // Local options verification
20430 if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') {
20440 finalOptions = _setWriteConcernHash(options);
20450 } else if(options.safe != null && typeof options.safe == 'object') {
20460 finalOptions = _setWriteConcernHash(options.safe);
20470 } else if(typeof options.safe == "boolean") {
20480 finalOptions = {w: (options.safe ? 1 : 0)};
20490 } else if(self.options.w != null || typeof self.options.j == 'boolean' || typeof self.options.journal == 'boolean' || typeof self.options.fsync == 'boolean') {
20500 finalOptions = _setWriteConcernHash(self.options);
20510 } else if(self.safe.w != null || typeof self.safe.j == 'boolean' || typeof self.safe.journal == 'boolean' || typeof self.safe.fsync == 'boolean') {
20520 finalOptions = _setWriteConcernHash(self.safe);
20530 } else if(typeof self.safe == "boolean") {
20540 finalOptions = {w: (self.safe ? 1 : 0)};
2055 }
2056
2057 // Ensure we don't have an invalid combination of write concerns
20580 if(finalOptions.w < 1
20590 && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowledgement using w < 1 cannot be combined with journal:true or fsync:true");
2060
2061 // Return the options
20620 return finalOptions;
2063};
2064
2065/**
2066 * Legacy support
2067 *
2068 * @ignore
2069 * @api private
2070 */
20711exports.connect = Db.connect;
20721exports.Db = Db;
2073
2074/**
2075 * Remove all listeners to the db instance.
2076 * @ignore
2077 * @api private
2078 */
20791Db.prototype.removeAllEventListeners = function() {
20800 this.removeAllListeners("close");
20810 this.removeAllListeners("error");
20820 this.removeAllListeners("timeout");
20830 this.removeAllListeners("parseError");
20840 this.removeAllListeners("poolReady");
20850 this.removeAllListeners("message");
2086};
2087

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/chunk.js

16%
77
13
64
LineHitsSource
11var Binary = require('bson').Binary,
2 ObjectID = require('bson').ObjectID;
3
4/**
5 * Class for representing a single chunk in GridFS.
6 *
7 * @class
8 *
9 * @param file {GridStore} The {@link GridStore} object holding this chunk.
10 * @param mongoObject {object} The mongo object representation of this chunk.
11 *
12 * @throws Error when the type of data field for {@link mongoObject} is not
13 * supported. Currently supported types for data field are instances of
14 * {@link String}, {@link Array}, {@link Binary} and {@link Binary}
15 * from the bson module
16 *
17 * @see Chunk#buildMongoObject
18 */
191var Chunk = exports.Chunk = function(file, mongoObject, writeConcern) {
200 if(!(this instanceof Chunk)) return new Chunk(file, mongoObject);
21
220 this.file = file;
230 var self = this;
240 var mongoObjectFinal = mongoObject == null ? {} : mongoObject;
250 this.writeConcern = writeConcern || {w:1};
260 this.objectId = mongoObjectFinal._id == null ? new ObjectID() : mongoObjectFinal._id;
270 this.chunkNumber = mongoObjectFinal.n == null ? 0 : mongoObjectFinal.n;
280 this.data = new Binary();
29
300 if(mongoObjectFinal.data == null) {
310 } else if(typeof mongoObjectFinal.data == "string") {
320 var buffer = new Buffer(mongoObjectFinal.data.length);
330 buffer.write(mongoObjectFinal.data, 'binary', 0);
340 this.data = new Binary(buffer);
350 } else if(Array.isArray(mongoObjectFinal.data)) {
360 var buffer = new Buffer(mongoObjectFinal.data.length);
370 buffer.write(mongoObjectFinal.data.join(''), 'binary', 0);
380 this.data = new Binary(buffer);
390 } else if(mongoObjectFinal.data instanceof Binary || Object.prototype.toString.call(mongoObjectFinal.data) == "[object Binary]") {
400 this.data = mongoObjectFinal.data;
410 } else if(Buffer.isBuffer(mongoObjectFinal.data)) {
42 } else {
430 throw Error("Illegal chunk format");
44 }
45 // Update position
460 this.internalPosition = 0;
47};
48
49/**
50 * Writes a data to this object and advance the read/write head.
51 *
52 * @param data {string} the data to write
53 * @param callback {function(*, GridStore)} This will be called after executing
54 * this method. The first parameter will contain null and the second one
55 * will contain a reference to this object.
56 */
571Chunk.prototype.write = function(data, callback) {
580 this.data.write(data, this.internalPosition);
590 this.internalPosition = this.data.length();
600 if(callback != null) return callback(null, this);
610 return this;
62};
63
64/**
65 * Reads data and advances the read/write head.
66 *
67 * @param length {number} The length of data to read.
68 *
69 * @return {string} The data read if the given length will not exceed the end of
70 * the chunk. Returns an empty String otherwise.
71 */
721Chunk.prototype.read = function(length) {
73 // Default to full read if no index defined
740 length = length == null || length == 0 ? this.length() : length;
75
760 if(this.length() - this.internalPosition + 1 >= length) {
770 var data = this.data.read(this.internalPosition, length);
780 this.internalPosition = this.internalPosition + length;
790 return data;
80 } else {
810 return '';
82 }
83};
84
851Chunk.prototype.readSlice = function(length) {
860 if ((this.length() - this.internalPosition) >= length) {
870 var data = null;
880 if (this.data.buffer != null) { //Pure BSON
890 data = this.data.buffer.slice(this.internalPosition, this.internalPosition + length);
90 } else { //Native BSON
910 data = new Buffer(length);
920 length = this.data.readInto(data, this.internalPosition);
93 }
940 this.internalPosition = this.internalPosition + length;
950 return data;
96 } else {
970 return null;
98 }
99};
100
101/**
102 * Checks if the read/write head is at the end.
103 *
104 * @return {boolean} Whether the read/write head has reached the end of this
105 * chunk.
106 */
1071Chunk.prototype.eof = function() {
1080 return this.internalPosition == this.length() ? true : false;
109};
110
111/**
112 * Reads one character from the data of this chunk and advances the read/write
113 * head.
114 *
115 * @return {string} a single character data read if the the read/write head is
116 * not at the end of the chunk. Returns an empty String otherwise.
117 */
1181Chunk.prototype.getc = function() {
1190 return this.read(1);
120};
121
122/**
123 * Clears the contents of the data in this chunk and resets the read/write head
124 * to the initial position.
125 */
1261Chunk.prototype.rewind = function() {
1270 this.internalPosition = 0;
1280 this.data = new Binary();
129};
130
131/**
132 * Saves this chunk to the database. Also overwrites existing entries having the
133 * same id as this chunk.
134 *
135 * @param callback {function(*, GridStore)} This will be called after executing
136 * this method. The first parameter will contain null and the second one
137 * will contain a reference to this object.
138 */
1391Chunk.prototype.save = function(callback) {
1400 var self = this;
141
1420 self.file.chunkCollection(function(err, collection) {
1430 if(err) return callback(err);
144
1450 collection.remove({'_id':self.objectId}, self.writeConcern, function(err, result) {
1460 if(err) return callback(err);
147
1480 if(self.data.length() > 0) {
1490 self.buildMongoObject(function(mongoObject) {
1500 var options = {forceServerObjectId:true};
1510 for(var name in self.writeConcern) {
1520 options[name] = self.writeConcern[name];
153 }
154
1550 collection.insert(mongoObject, options, function(err, collection) {
1560 callback(err, self);
157 });
158 });
159 } else {
1600 callback(null, self);
161 }
162 });
163 });
164};
165
166/**
167 * Creates a mongoDB object representation of this chunk.
168 *
169 * @param callback {function(Object)} This will be called after executing this
170 * method. The object will be passed to the first parameter and will have
171 * the structure:
172 *
173 * <pre><code>
174 * {
175 * '_id' : , // {number} id for this chunk
176 * 'files_id' : , // {number} foreign key to the file collection
177 * 'n' : , // {number} chunk number
178 * 'data' : , // {bson#Binary} the chunk data itself
179 * }
180 * </code></pre>
181 *
182 * @see <a href="http://www.mongodb.org/display/DOCS/GridFS+Specification#GridFSSpecification-{{chunks}}">MongoDB GridFS Chunk Object Structure</a>
183 */
1841Chunk.prototype.buildMongoObject = function(callback) {
1850 var mongoObject = {
186 'files_id': this.file.fileId,
187 'n': this.chunkNumber,
188 'data': this.data};
189 // If we are saving using a specific ObjectId
1900 if(this.objectId != null) mongoObject._id = this.objectId;
191
1920 callback(mongoObject);
193};
194
195/**
196 * @return {number} the length of the data
197 */
1981Chunk.prototype.length = function() {
1990 return this.data.length();
200};
201
202/**
203 * The position of the read/write head
204 * @name position
205 * @lends Chunk#
206 * @field
207 */
2081Object.defineProperty(Chunk.prototype, "position", { enumerable: true
209 , get: function () {
2100 return this.internalPosition;
211 }
212 , set: function(value) {
2130 this.internalPosition = value;
214 }
215});
216
217/**
218 * The default chunk size
219 * @constant
220 */
2211Chunk.DEFAULT_CHUNK_SIZE = 1024 * 256;
222

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/grid.js

18%
33
6
27
LineHitsSource
11var GridStore = require('./gridstore').GridStore,
2 ObjectID = require('bson').ObjectID;
3
4/**
5 * A class representation of a simple Grid interface.
6 *
7 * @class Represents the Grid.
8 * @param {Db} db A database instance to interact with.
9 * @param {String} [fsName] optional different root collection for GridFS.
10 * @return {Grid}
11 */
121function Grid(db, fsName) {
13
140 if(!(this instanceof Grid)) return new Grid(db, fsName);
15
160 this.db = db;
170 this.fsName = fsName == null ? GridStore.DEFAULT_ROOT_COLLECTION : fsName;
18}
19
20/**
21 * Puts binary data to the grid
22 *
23 * Options
24 * - **_id** {Any}, unique id for this file
25 * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
26 * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**.
27 * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**.
28 * - **metadata** {Object}, arbitrary data the user wants to store.
29 *
30 * @param {Buffer} data buffer with Binary Data.
31 * @param {Object} [options] the options for the files.
32 * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
33 * @return {null}
34 * @api public
35 */
361Grid.prototype.put = function(data, options, callback) {
370 var self = this;
380 var args = Array.prototype.slice.call(arguments, 1);
390 callback = args.pop();
400 options = args.length ? args.shift() : {};
41 // If root is not defined add our default one
420 options['root'] = options['root'] == null ? this.fsName : options['root'];
43
44 // Return if we don't have a buffer object as data
450 if(!(Buffer.isBuffer(data))) return callback(new Error("Data object must be a buffer object"), null);
46 // Get filename if we are using it
470 var filename = options['filename'] || null;
48 // Get id if we are using it
490 var id = options['_id'] || null;
50 // Create gridstore
510 var gridStore = new GridStore(this.db, id, filename, "w", options);
520 gridStore.open(function(err, gridStore) {
530 if(err) return callback(err, null);
54
550 gridStore.write(data, function(err, result) {
560 if(err) return callback(err, null);
57
580 gridStore.close(function(err, result) {
590 if(err) return callback(err, null);
600 callback(null, result);
61 })
62 })
63 })
64}
65
66/**
67 * Get binary data to the grid
68 *
69 * @param {Any} id for file.
70 * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
71 * @return {null}
72 * @api public
73 */
741Grid.prototype.get = function(id, callback) {
75 // Create gridstore
760 var gridStore = new GridStore(this.db, id, null, "r", {root:this.fsName});
770 gridStore.open(function(err, gridStore) {
780 if(err) return callback(err, null);
79
80 // Return the data
810 gridStore.read(function(err, data) {
820 return callback(err, data)
83 });
84 })
85}
86
87/**
88 * Delete file from grid
89 *
90 * @param {Any} id for file.
91 * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
92 * @return {null}
93 * @api public
94 */
951Grid.prototype.delete = function(id, callback) {
96 // Create gridstore
970 GridStore.unlink(this.db, id, {root:this.fsName}, function(err, result) {
980 if(err) return callback(err, false);
990 return callback(null, true);
100 });
101}
102
1031exports.Grid = Grid;
104

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js

9%
621
62
559
LineHitsSource
1/**
2 * @fileOverview GridFS is a tool for MongoDB to store files to the database.
3 * Because of the restrictions of the object size the database can hold, a
4 * facility to split a file into several chunks is needed. The {@link GridStore}
5 * class offers a simplified api to interact with files while managing the
6 * chunks of split files behind the scenes. More information about GridFS can be
7 * found <a href="http://www.mongodb.org/display/DOCS/GridFS">here</a>.
8 */
91var Chunk = require('./chunk').Chunk,
10 DbCommand = require('../commands/db_command').DbCommand,
11 ObjectID = require('bson').ObjectID,
12 Buffer = require('buffer').Buffer,
13 fs = require('fs'),
14 timers = require('timers'),
15 util = require('util'),
16 inherits = util.inherits,
17 ReadStream = require('./readstream').ReadStream,
18 Stream = require('stream');
19
20// Set processor, setImmediate if 0.10 otherwise nextTick
211var processor = require('../utils').processor();
22
231var REFERENCE_BY_FILENAME = 0,
24 REFERENCE_BY_ID = 1;
25
26/**
27 * A class representation of a file stored in GridFS.
28 *
29 * Modes
30 * - **"r"** - read only. This is the default mode.
31 * - **"w"** - write in truncate mode. Existing data will be overwriten.
32 * - **w+"** - write in edit mode.
33 *
34 * Options
35 * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
36 * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**.
37 * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**.
38 * - **metadata** {Object}, arbitrary data the user wants to store.
39 * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
40 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
41 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
42 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
43 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
44 *
45 * @class Represents the GridStore.
46 * @param {Db} db A database instance to interact with.
47 * @param {Any} [id] optional unique id for this file
48 * @param {String} [filename] optional filename for this file, no unique constrain on the field
49 * @param {String} mode set the mode for this file.
50 * @param {Object} options optional properties to specify.
51 * @return {GridStore}
52 */
531var GridStore = function GridStore(db, id, filename, mode, options) {
540 if(!(this instanceof GridStore)) return new GridStore(db, id, filename, mode, options);
55
560 var self = this;
570 this.db = db;
58
59 // Call stream constructor
600 if(typeof Stream == 'function') {
610 Stream.call(this);
62 } else {
63 // 0.4.X backward compatibility fix
640 Stream.Stream.call(this);
65 }
66
67 // Handle options
680 if(typeof options === 'undefined') options = {};
69 // Handle mode
700 if(typeof mode === 'undefined') {
710 mode = filename;
720 filename = undefined;
730 } else if(typeof mode == 'object') {
740 options = mode;
750 mode = filename;
760 filename = undefined;
77 }
78
790 if(id instanceof ObjectID) {
800 this.referenceBy = REFERENCE_BY_ID;
810 this.fileId = id;
820 this.filename = filename;
830 } else if(typeof filename == 'undefined') {
840 this.referenceBy = REFERENCE_BY_FILENAME;
850 this.filename = id;
860 if (mode.indexOf('w') != null) {
870 this.fileId = new ObjectID();
88 }
89 } else {
900 this.referenceBy = REFERENCE_BY_ID;
910 this.fileId = id;
920 this.filename = filename;
93 }
94
95 // Set up the rest
960 this.mode = mode == null ? "r" : mode;
970 this.options = options == null ? {w:1} : options;
98
99 // If we have no write concerns set w:1 as default
1000 if(this.options.w == null
101 && this.options.j == null
1020 && this.options.fsync == null) this.options.w = 1;
103
104 // Set the root if overridden
1050 this.root = this.options['root'] == null ? exports.GridStore.DEFAULT_ROOT_COLLECTION : this.options['root'];
1060 this.position = 0;
1070 this.readPreference = this.options.readPreference || 'primary';
1080 this.writeConcern = _getWriteConcern(this, this.options);
109 // Set default chunk size
1100 this.internalChunkSize = this.options['chunkSize'] == null ? Chunk.DEFAULT_CHUNK_SIZE : this.options['chunkSize'];
111}
112
113/**
114 * Code for the streaming capabilities of the gridstore object
115 * Most code from Aaron heckmanns project https://github.com/aheckmann/gridfs-stream
116 * Modified to work on the gridstore object itself
117 * @ignore
118 */
1191if(typeof Stream == 'function') {
1201 GridStore.prototype = { __proto__: Stream.prototype }
121} else {
122 // Node 0.4.X compatibility code
1230 GridStore.prototype = { __proto__: Stream.Stream.prototype }
124}
125
126// Move pipe to _pipe
1271GridStore.prototype._pipe = GridStore.prototype.pipe;
128
129/**
130 * Opens the file from the database and initialize this object. Also creates a
131 * new one if file does not exist.
132 *
133 * @param {Function} callback this will be called after executing this method. The first parameter will contain an **{Error}** object and the second parameter will be null if an error occured. Otherwise, the first parameter will be null and the second will contain the reference to this object.
134 * @return {null}
135 * @api public
136 */
1371GridStore.prototype.open = function(callback) {
1380 if( this.mode != "w" && this.mode != "w+" && this.mode != "r"){
1390 callback(new Error("Illegal mode " + this.mode), null);
1400 return;
141 }
142
1430 var self = this;
144 // If we are writing we need to ensure we have the right indexes for md5's
1450 if((self.mode == "w" || self.mode == "w+")) {
146 // Get files collection
1470 self.collection(function(err, collection) {
1480 if(err) return callback(err);
149
150 // Put index on filename
1510 collection.ensureIndex([['filename', 1]], function(err, index) {
1520 if(err) return callback(err);
153
154 // Get chunk collection
1550 self.chunkCollection(function(err, chunkCollection) {
1560 if(err) return callback(err);
157
158 // Ensure index on chunk collection
1590 chunkCollection.ensureIndex([['files_id', 1], ['n', 1]], function(err, index) {
1600 if(err) return callback(err);
1610 _open(self, callback);
162 });
163 });
164 });
165 });
166 } else {
167 // Open the gridstore
1680 _open(self, callback);
169 }
170};
171
172/**
173 * Hidding the _open function
174 * @ignore
175 * @api private
176 */
1771var _open = function(self, callback) {
1780 self.collection(function(err, collection) {
1790 if(err!==null) {
1800 callback(new Error("at collection: "+err), null);
1810 return;
182 }
183
184 // Create the query
1850 var query = self.referenceBy == REFERENCE_BY_ID ? {_id:self.fileId} : {filename:self.filename};
1860 query = null == self.fileId && this.filename == null ? null : query;
187
188 // Fetch the chunks
1890 if(query != null) {
1900 collection.find(query, {readPreference:self.readPreference}, function(err, cursor) {
1910 if(err) return error(err);
192
193 // Fetch the file
1940 cursor.nextObject(function(err, doc) {
1950 if(err) return error(err);
196
197 // Check if the collection for the files exists otherwise prepare the new one
1980 if(doc != null) {
1990 self.fileId = doc._id;
2000 self.filename = doc.filename;
2010 self.contentType = doc.contentType;
2020 self.internalChunkSize = doc.chunkSize;
2030 self.uploadDate = doc.uploadDate;
2040 self.aliases = doc.aliases;
2050 self.length = doc.length;
2060 self.metadata = doc.metadata;
2070 self.internalMd5 = doc.md5;
2080 } else if (self.mode != 'r') {
2090 self.fileId = self.fileId == null ? new ObjectID() : self.fileId;
2100 self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE;
2110 self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize;
2120 self.length = 0;
213 } else {
2140 self.length = 0;
2150 var txtId = self.fileId instanceof ObjectID ? self.fileId.toHexString() : self.fileId;
2160 return error(new Error((self.referenceBy == REFERENCE_BY_ID ? txtId : self.filename) + " does not exist", self));
217 }
218
219 // Process the mode of the object
2200 if(self.mode == "r") {
2210 nthChunk(self, 0, function(err, chunk) {
2220 if(err) return error(err);
2230 self.currentChunk = chunk;
2240 self.position = 0;
2250 callback(null, self);
226 });
2270 } else if(self.mode == "w") {
228 // Delete any existing chunks
2290 deleteChunks(self, function(err, result) {
2300 if(err) return error(err);
2310 self.currentChunk = new Chunk(self, {'n':0}, self.writeConcern);
2320 self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type'];
2330 self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size'];
2340 self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
2350 self.position = 0;
2360 callback(null, self);
237 });
2380 } else if(self.mode == "w+") {
2390 nthChunk(self, lastChunkNumber(self), function(err, chunk) {
2400 if(err) return error(err);
241 // Set the current chunk
2420 self.currentChunk = chunk == null ? new Chunk(self, {'n':0}, self.writeConcern) : chunk;
2430 self.currentChunk.position = self.currentChunk.data.length();
2440 self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
2450 self.position = self.length;
2460 callback(null, self);
247 });
248 }
249 });
250 });
251 } else {
252 // Write only mode
2530 self.fileId = null == self.fileId ? new ObjectID() : self.fileId;
2540 self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE;
2550 self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize;
2560 self.length = 0;
257
2580 self.chunkCollection(function(err, collection2) {
2590 if(err) return error(err);
260
261 // No file exists set up write mode
2620 if(self.mode == "w") {
263 // Delete any existing chunks
2640 deleteChunks(self, function(err, result) {
2650 if(err) return error(err);
2660 self.currentChunk = new Chunk(self, {'n':0}, self.writeConcern);
2670 self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type'];
2680 self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size'];
2690 self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
2700 self.position = 0;
2710 callback(null, self);
272 });
2730 } else if(self.mode == "w+") {
2740 nthChunk(self, lastChunkNumber(self), function(err, chunk) {
2750 if(err) return error(err);
276 // Set the current chunk
2770 self.currentChunk = chunk == null ? new Chunk(self, {'n':0}, self.writeConcern) : chunk;
2780 self.currentChunk.position = self.currentChunk.data.length();
2790 self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
2800 self.position = self.length;
2810 callback(null, self);
282 });
283 }
284 });
285 }
286 });
287
288 // only pass error to callback once
2890 function error (err) {
2900 if(error.err) return;
2910 callback(error.err = err);
292 }
293};
294
295/**
296 * Stores a file from the file system to the GridFS database.
297 *
298 * @param {String|Buffer|FileHandle} file the file to store.
299 * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the the second will contain the reference to this object.
300 * @return {null}
301 * @api public
302 */
3031GridStore.prototype.writeFile = function (file, callback) {
3040 var self = this;
3050 if (typeof file === 'string') {
3060 fs.open(file, 'r', function (err, fd) {
3070 if(err) return callback(err);
3080 self.writeFile(fd, callback);
309 });
3100 return;
311 }
312
3130 self.open(function (err, self) {
3140 if(err) return callback(err, self);
315
3160 fs.fstat(file, function (err, stats) {
3170 if(err) return callback(err, self);
318
3190 var offset = 0;
3200 var index = 0;
3210 var numberOfChunksLeft = Math.min(stats.size / self.chunkSize);
322
323 // Write a chunk
3240 var writeChunk = function() {
3250 fs.read(file, self.chunkSize, offset, 'binary', function(err, data, bytesRead) {
3260 if(err) return callback(err, self);
327
3280 offset = offset + bytesRead;
329
330 // Create a new chunk for the data
3310 var chunk = new Chunk(self, {n:index++}, self.writeConcern);
3320 chunk.write(data, function(err, chunk) {
3330 if(err) return callback(err, self);
334
3350 chunk.save(function(err, result) {
3360 if(err) return callback(err, self);
337
3380 self.position = self.position + data.length;
339
340 // Point to current chunk
3410 self.currentChunk = chunk;
342
3430 if(offset >= stats.size) {
3440 fs.close(file);
3450 self.close(function(err, result) {
3460 if(err) return callback(err, self);
3470 return callback(null, self);
348 });
349 } else {
3500 return processor(writeChunk);
351 }
352 });
353 });
354 });
355 }
356
357 // Process the first write
3580 processor(writeChunk);
359 });
360 });
361};
362
363/**
364 * Writes some data. This method will work properly only if initialized with mode
365 * "w" or "w+".
366 *
367 * @param string {string} The data to write.
368 * @param close {boolean=false} opt_argument Closes this file after writing if
369 * true.
370 * @param callback {function(*, GridStore)} This will be called after executing
371 * this method. The first parameter will contain null and the second one
372 * will contain a reference to this object.
373 *
374 * @ignore
375 * @api private
376 */
3771var writeBuffer = function(self, buffer, close, callback) {
3780 if(typeof close === "function") { callback = close; close = null; }
3790 var finalClose = (close == null) ? false : close;
380
3810 if(self.mode[0] != "w") {
3820 callback(new Error((self.referenceBy == REFERENCE_BY_ID ? self.toHexString() : self.filename) + " not opened for writing"), null);
383 } else {
3840 if(self.currentChunk.position + buffer.length >= self.chunkSize) {
385 // Write out the current Chunk and then keep writing until we have less data left than a chunkSize left
386 // to a new chunk (recursively)
3870 var previousChunkNumber = self.currentChunk.chunkNumber;
3880 var leftOverDataSize = self.chunkSize - self.currentChunk.position;
3890 var firstChunkData = buffer.slice(0, leftOverDataSize);
3900 var leftOverData = buffer.slice(leftOverDataSize);
391 // A list of chunks to write out
3920 var chunksToWrite = [self.currentChunk.write(firstChunkData)];
393 // If we have more data left than the chunk size let's keep writing new chunks
3940 while(leftOverData.length >= self.chunkSize) {
395 // Create a new chunk and write to it
3960 var newChunk = new Chunk(self, {'n': (previousChunkNumber + 1)}, self.writeConcern);
3970 var firstChunkData = leftOverData.slice(0, self.chunkSize);
3980 leftOverData = leftOverData.slice(self.chunkSize);
399 // Update chunk number
4000 previousChunkNumber = previousChunkNumber + 1;
401 // Write data
4020 newChunk.write(firstChunkData);
403 // Push chunk to save list
4040 chunksToWrite.push(newChunk);
405 }
406
407 // Set current chunk with remaining data
4080 self.currentChunk = new Chunk(self, {'n': (previousChunkNumber + 1)}, self.writeConcern);
409 // If we have left over data write it
4100 if(leftOverData.length > 0) self.currentChunk.write(leftOverData);
411
412 // Update the position for the gridstore
4130 self.position = self.position + buffer.length;
414 // Total number of chunks to write
4150 var numberOfChunksToWrite = chunksToWrite.length;
416 // Write out all the chunks and then return
4170 for(var i = 0; i < chunksToWrite.length; i++) {
4180 var chunk = chunksToWrite[i];
4190 chunk.save(function(err, result) {
4200 if(err) return callback(err);
421
4220 numberOfChunksToWrite = numberOfChunksToWrite - 1;
423
4240 if(numberOfChunksToWrite <= 0) {
4250 return callback(null, self);
426 }
427 })
428 }
429 } else {
430 // Update the position for the gridstore
4310 self.position = self.position + buffer.length;
432 // We have less data than the chunk size just write it and callback
4330 self.currentChunk.write(buffer);
4340 callback(null, self);
435 }
436 }
437};
438
439/**
440 * Creates a mongoDB object representation of this object.
441 *
442 * @param callback {function(object)} This will be called after executing this
443 * method. The object will be passed to the first parameter and will have
444 * the structure:
445 *
446 * <pre><code>
447 * {
448 * '_id' : , // {number} id for this file
449 * 'filename' : , // {string} name for this file
450 * 'contentType' : , // {string} mime type for this file
451 * 'length' : , // {number} size of this file?
452 * 'chunksize' : , // {number} chunk size used by this file
453 * 'uploadDate' : , // {Date}
454 * 'aliases' : , // {array of string}
455 * 'metadata' : , // {string}
456 * }
457 * </code></pre>
458 *
459 * @ignore
460 * @api private
461 */
4621var buildMongoObject = function(self, callback) {
463 // Calcuate the length
4640 var mongoObject = {
465 '_id': self.fileId,
466 'filename': self.filename,
467 'contentType': self.contentType,
468 'length': self.position ? self.position : 0,
469 'chunkSize': self.chunkSize,
470 'uploadDate': self.uploadDate,
471 'aliases': self.aliases,
472 'metadata': self.metadata
473 };
474
4750 var md5Command = {filemd5:self.fileId, root:self.root};
4760 self.db.command(md5Command, function(err, results) {
4770 mongoObject.md5 = results.md5;
4780 callback(mongoObject);
479 });
480};
481
482/**
483 * Saves this file to the database. This will overwrite the old entry if it
484 * already exists. This will work properly only if mode was initialized to
485 * "w" or "w+".
486 *
487 * @param {Function} callback this will be called after executing this method. Passes an **{Error}** object to the first parameter and null to the second if an error occured. Otherwise, passes null to the first and a reference to this object to the second.
488 * @return {null}
489 * @api public
490 */
4911GridStore.prototype.close = function(callback) {
4920 var self = this;
493
4940 if(self.mode[0] == "w") {
4950 if(self.currentChunk != null && self.currentChunk.position > 0) {
4960 self.currentChunk.save(function(err, chunk) {
4970 if(err && typeof callback == 'function') return callback(err);
498
4990 self.collection(function(err, files) {
5000 if(err && typeof callback == 'function') return callback(err);
501
502 // Build the mongo object
5030 if(self.uploadDate != null) {
5040 files.remove({'_id':self.fileId}, {safe:true}, function(err, collection) {
5050 if(err && typeof callback == 'function') return callback(err);
506
5070 buildMongoObject(self, function(mongoObject) {
5080 files.save(mongoObject, self.writeConcern, function(err) {
5090 if(typeof callback == 'function')
5100 callback(err, mongoObject);
511 });
512 });
513 });
514 } else {
5150 self.uploadDate = new Date();
5160 buildMongoObject(self, function(mongoObject) {
5170 files.save(mongoObject, self.writeConcern, function(err) {
5180 if(typeof callback == 'function')
5190 callback(err, mongoObject);
520 });
521 });
522 }
523 });
524 });
525 } else {
5260 self.collection(function(err, files) {
5270 if(err && typeof callback == 'function') return callback(err);
528
5290 self.uploadDate = new Date();
5300 buildMongoObject(self, function(mongoObject) {
5310 files.save(mongoObject, self.writeConcern, function(err) {
5320 if(typeof callback == 'function')
5330 callback(err, mongoObject);
534 });
535 });
536 });
537 }
5380 } else if(self.mode[0] == "r") {
5390 if(typeof callback == 'function')
5400 callback(null, null);
541 } else {
5420 if(typeof callback == 'function')
5430 callback(new Error("Illegal mode " + self.mode), null);
544 }
545};
546
547/**
548 * Gets the nth chunk of this file.
549 *
550 * @param chunkNumber {number} The nth chunk to retrieve.
551 * @param callback {function(*, Chunk|object)} This will be called after
552 * executing this method. null will be passed to the first parameter while
553 * a new {@link Chunk} instance will be passed to the second parameter if
554 * the chunk was found or an empty object {} if not.
555 *
556 * @ignore
557 * @api private
558 */
5591var nthChunk = function(self, chunkNumber, callback) {
5600 self.chunkCollection(function(err, collection) {
5610 if(err) return callback(err);
562
5630 collection.find({'files_id':self.fileId, 'n':chunkNumber}, {readPreference: self.readPreference}, function(err, cursor) {
5640 if(err) return callback(err);
565
5660 cursor.nextObject(function(err, chunk) {
5670 if(err) return callback(err);
568
5690 var finalChunk = chunk == null ? {} : chunk;
5700 callback(null, new Chunk(self, finalChunk, self.writeConcern));
571 });
572 });
573 });
574};
575
576/**
577 *
578 * @ignore
579 * @api private
580 */
5811GridStore.prototype._nthChunk = function(chunkNumber, callback) {
5820 nthChunk(this, chunkNumber, callback);
583}
584
585/**
586 * @return {Number} The last chunk number of this file.
587 *
588 * @ignore
589 * @api private
590 */
5911var lastChunkNumber = function(self) {
5920 return Math.floor(self.length/self.chunkSize);
593};
594
595/**
596 * Retrieve this file's chunks collection.
597 *
598 * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured.
599 * @return {null}
600 * @api public
601 */
6021GridStore.prototype.chunkCollection = function(callback) {
6030 this.db.collection((this.root + ".chunks"), callback);
604};
605
606/**
607 * Deletes all the chunks of this file in the database.
608 *
609 * @param callback {function(*, boolean)} This will be called after this method
610 * executes. Passes null to the first and true to the second argument.
611 *
612 * @ignore
613 * @api private
614 */
6151var deleteChunks = function(self, callback) {
6160 if(self.fileId != null) {
6170 self.chunkCollection(function(err, collection) {
6180 if(err) return callback(err, false);
6190 collection.remove({'files_id':self.fileId}, {safe:true}, function(err, result) {
6200 if(err) return callback(err, false);
6210 callback(null, true);
622 });
623 });
624 } else {
6250 callback(null, true);
626 }
627};
628
629/**
630 * Deletes all the chunks of this file in the database.
631 *
632 * @param {Function} callback this will be called after this method executes. Passes null to the first and true to the second argument.
633 * @return {null}
634 * @api public
635 */
6361GridStore.prototype.unlink = function(callback) {
6370 var self = this;
6380 deleteChunks(this, function(err) {
6390 if(err!==null) {
6400 err.message = "at deleteChunks: " + err.message;
6410 return callback(err);
642 }
643
6440 self.collection(function(err, collection) {
6450 if(err!==null) {
6460 err.message = "at collection: " + err.message;
6470 return callback(err);
648 }
649
6500 collection.remove({'_id':self.fileId}, {safe:true}, function(err) {
6510 callback(err, self);
652 });
653 });
654 });
655};
656
657/**
658 * Retrieves the file collection associated with this object.
659 *
660 * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured.
661 * @return {null}
662 * @api public
663 */
6641GridStore.prototype.collection = function(callback) {
6650 this.db.collection(this.root + ".files", callback);
666};
667
668/**
669 * Reads the data of this file.
670 *
671 * @param {String} [separator] the character to be recognized as the newline separator.
672 * @param {Function} callback This will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character.
673 * @return {null}
674 * @api public
675 */
6761GridStore.prototype.readlines = function(separator, callback) {
6770 var args = Array.prototype.slice.call(arguments, 0);
6780 callback = args.pop();
6790 separator = args.length ? args.shift() : "\n";
680
6810 this.read(function(err, data) {
6820 if(err) return callback(err);
683
6840 var items = data.toString().split(separator);
6850 items = items.length > 0 ? items.splice(0, items.length - 1) : [];
6860 for(var i = 0; i < items.length; i++) {
6870 items[i] = items[i] + separator;
688 }
689
6900 callback(null, items);
691 });
692};
693
694/**
695 * Deletes all the chunks of this file in the database if mode was set to "w" or
696 * "w+" and resets the read/write head to the initial position.
697 *
698 * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
699 * @return {null}
700 * @api public
701 */
7021GridStore.prototype.rewind = function(callback) {
7030 var self = this;
704
7050 if(this.currentChunk.chunkNumber != 0) {
7060 if(this.mode[0] == "w") {
7070 deleteChunks(self, function(err, gridStore) {
7080 if(err) return callback(err);
7090 self.currentChunk = new Chunk(self, {'n': 0}, self.writeConcern);
7100 self.position = 0;
7110 callback(null, self);
712 });
713 } else {
7140 self.currentChunk(0, function(err, chunk) {
7150 if(err) return callback(err);
7160 self.currentChunk = chunk;
7170 self.currentChunk.rewind();
7180 self.position = 0;
7190 callback(null, self);
720 });
721 }
722 } else {
7230 self.currentChunk.rewind();
7240 self.position = 0;
7250 callback(null, self);
726 }
727};
728
729/**
730 * Retrieves the contents of this file and advances the read/write head. Works with Buffers only.
731 *
732 * There are 3 signatures for this method:
733 *
734 * (callback)
735 * (length, callback)
736 * (length, buffer, callback)
737 *
738 * @param {Number} [length] the number of characters to read. Reads all the characters from the read/write head to the EOF if not specified.
739 * @param {String|Buffer} [buffer] a string to hold temporary data. This is used for storing the string data read so far when recursively calling this method.
740 * @param {Function} callback this will be called after this method is executed. null will be passed to the first parameter and a string containing the contents of the buffer concatenated with the contents read from this file will be passed to the second.
741 * @return {null}
742 * @api public
743 */
7441GridStore.prototype.read = function(length, buffer, callback) {
7450 var self = this;
746
7470 var args = Array.prototype.slice.call(arguments, 0);
7480 callback = args.pop();
7490 length = args.length ? args.shift() : null;
7500 buffer = args.length ? args.shift() : null;
751
752 // The data is a c-terminated string and thus the length - 1
7530 var finalLength = length == null ? self.length - self.position : length;
7540 var finalBuffer = buffer == null ? new Buffer(finalLength) : buffer;
755 // Add a index to buffer to keep track of writing position or apply current index
7560 finalBuffer._index = buffer != null && buffer._index != null ? buffer._index : 0;
757
7580 if((self.currentChunk.length() - self.currentChunk.position + finalBuffer._index) >= finalLength) {
7590 var slice = self.currentChunk.readSlice(finalLength - finalBuffer._index);
760 // Copy content to final buffer
7610 slice.copy(finalBuffer, finalBuffer._index);
762 // Update internal position
7630 self.position = self.position + finalBuffer.length;
764 // Check if we don't have a file at all
7650 if(finalLength == 0 && finalBuffer.length == 0) return callback(new Error("File does not exist"), null);
766 // Else return data
7670 callback(null, finalBuffer);
768 } else {
7690 var slice = self.currentChunk.readSlice(self.currentChunk.length() - self.currentChunk.position);
770 // Copy content to final buffer
7710 slice.copy(finalBuffer, finalBuffer._index);
772 // Update index position
7730 finalBuffer._index += slice.length;
774
775 // Load next chunk and read more
7760 nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) {
7770 if(err) return callback(err);
778
7790 if(chunk.length() > 0) {
7800 self.currentChunk = chunk;
7810 self.read(length, finalBuffer, callback);
782 } else {
7830 if (finalBuffer._index > 0) {
7840 callback(null, finalBuffer)
785 } else {
7860 callback(new Error("no chunks found for file, possibly corrupt"), null);
787 }
788 }
789 });
790 }
791}
792
793/**
794 * Retrieves the position of the read/write head of this file.
795 *
796 * @param {Function} callback This gets called after this method terminates. null is passed to the first parameter and the position is passed to the second.
797 * @return {null}
798 * @api public
799 */
8001GridStore.prototype.tell = function(callback) {
8010 callback(null, this.position);
802};
803
804/**
805 * Moves the read/write head to a new location.
806 *
807 * There are 3 signatures for this method
808 *
809 * Seek Location Modes
810 * - **GridStore.IO_SEEK_SET**, **(default)** set the position from the start of the file.
811 * - **GridStore.IO_SEEK_CUR**, set the position from the current position in the file.
812 * - **GridStore.IO_SEEK_END**, set the position from the end of the file.
813 *
814 * @param {Number} [position] the position to seek to
815 * @param {Number} [seekLocation] seek mode. Use one of the Seek Location modes.
816 * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
817 * @return {null}
818 * @api public
819 */
8201GridStore.prototype.seek = function(position, seekLocation, callback) {
8210 var self = this;
822
8230 var args = Array.prototype.slice.call(arguments, 1);
8240 callback = args.pop();
8250 seekLocation = args.length ? args.shift() : null;
826
8270 var seekLocationFinal = seekLocation == null ? exports.GridStore.IO_SEEK_SET : seekLocation;
8280 var finalPosition = position;
8290 var targetPosition = 0;
830
831 // Calculate the position
8320 if(seekLocationFinal == exports.GridStore.IO_SEEK_CUR) {
8330 targetPosition = self.position + finalPosition;
8340 } else if(seekLocationFinal == exports.GridStore.IO_SEEK_END) {
8350 targetPosition = self.length + finalPosition;
836 } else {
8370 targetPosition = finalPosition;
838 }
839
840 // Get the chunk
8410 var newChunkNumber = Math.floor(targetPosition/self.chunkSize);
8420 if(newChunkNumber != self.currentChunk.chunkNumber) {
8430 var seekChunk = function() {
8440 nthChunk(self, newChunkNumber, function(err, chunk) {
8450 self.currentChunk = chunk;
8460 self.position = targetPosition;
8470 self.currentChunk.position = (self.position % self.chunkSize);
8480 callback(err, self);
849 });
850 };
851
8520 if(self.mode[0] == 'w') {
8530 self.currentChunk.save(function(err) {
8540 if(err) return callback(err);
8550 seekChunk();
856 });
857 } else {
8580 seekChunk();
859 }
860 } else {
8610 self.position = targetPosition;
8620 self.currentChunk.position = (self.position % self.chunkSize);
8630 callback(null, self);
864 }
865};
866
867/**
868 * Verify if the file is at EOF.
869 *
870 * @return {Boolean} true if the read/write head is at the end of this file.
871 * @api public
872 */
8731GridStore.prototype.eof = function() {
8740 return this.position == this.length ? true : false;
875};
876
877/**
878 * Retrieves a single character from this file.
879 *
880 * @param {Function} callback this gets called after this method is executed. Passes null to the first parameter and the character read to the second or null to the second if the read/write head is at the end of the file.
881 * @return {null}
882 * @api public
883 */
8841GridStore.prototype.getc = function(callback) {
8850 var self = this;
886
8870 if(self.eof()) {
8880 callback(null, null);
8890 } else if(self.currentChunk.eof()) {
8900 nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) {
8910 self.currentChunk = chunk;
8920 self.position = self.position + 1;
8930 callback(err, self.currentChunk.getc());
894 });
895 } else {
8960 self.position = self.position + 1;
8970 callback(null, self.currentChunk.getc());
898 }
899};
900
901/**
902 * Writes a string to the file with a newline character appended at the end if
903 * the given string does not have one.
904 *
905 * @param {String} string the string to write.
906 * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
907 * @return {null}
908 * @api public
909 */
9101GridStore.prototype.puts = function(string, callback) {
9110 var finalString = string.match(/\n$/) == null ? string + "\n" : string;
9120 this.write(finalString, callback);
913};
914
915/**
916 * Returns read stream based on this GridStore file
917 *
918 * Events
919 * - **data** {function(item) {}} the data event triggers when a document is ready.
920 * - **end** {function() {}} the end event triggers when there is no more documents available.
921 * - **close** {function() {}} the close event triggers when the stream is closed.
922 * - **error** {function(err) {}} the error event triggers if an error happens.
923 *
924 * @param {Boolean} autoclose if true current GridStore will be closed when EOF and 'close' event will be fired
925 * @return {null}
926 * @api public
927 */
9281GridStore.prototype.stream = function(autoclose) {
9290 return new ReadStream(autoclose, this);
930};
931
932/**
933* The collection to be used for holding the files and chunks collection.
934*
935* @classconstant DEFAULT_ROOT_COLLECTION
936**/
9371GridStore.DEFAULT_ROOT_COLLECTION = 'fs';
938
939/**
940* Default file mime type
941*
942* @classconstant DEFAULT_CONTENT_TYPE
943**/
9441GridStore.DEFAULT_CONTENT_TYPE = 'binary/octet-stream';
945
946/**
947* Seek mode where the given length is absolute.
948*
949* @classconstant IO_SEEK_SET
950**/
9511GridStore.IO_SEEK_SET = 0;
952
953/**
954* Seek mode where the given length is an offset to the current read/write head.
955*
956* @classconstant IO_SEEK_CUR
957**/
9581GridStore.IO_SEEK_CUR = 1;
959
960/**
961* Seek mode where the given length is an offset to the end of the file.
962*
963* @classconstant IO_SEEK_END
964**/
9651GridStore.IO_SEEK_END = 2;
966
967/**
968 * Checks if a file exists in the database.
969 *
970 * Options
971 * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
972 *
973 * @param {Db} db the database to query.
974 * @param {String} name the name of the file to look for.
975 * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
976 * @param {Function} callback this will be called after this method executes. Passes null to the first and passes true to the second if the file exists and false otherwise.
977 * @return {null}
978 * @api public
979 */
9801GridStore.exist = function(db, fileIdObject, rootCollection, options, callback) {
9810 var args = Array.prototype.slice.call(arguments, 2);
9820 callback = args.pop();
9830 rootCollection = args.length ? args.shift() : null;
9840 options = args.length ? args.shift() : {};
985
986 // Establish read preference
9870 var readPreference = options.readPreference || 'primary';
988 // Fetch collection
9890 var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION;
9900 db.collection(rootCollectionFinal + ".files", function(err, collection) {
9910 if(err) return callback(err);
992
993 // Build query
9940 var query = (typeof fileIdObject == 'string' || Object.prototype.toString.call(fileIdObject) == '[object RegExp]' )
995 ? {'filename':fileIdObject}
996 : {'_id':fileIdObject}; // Attempt to locate file
997
9980 collection.find(query, {readPreference:readPreference}, function(err, cursor) {
9990 if(err) return callback(err);
1000
10010 cursor.nextObject(function(err, item) {
10020 if(err) return callback(err);
10030 callback(null, item == null ? false : true);
1004 });
1005 });
1006 });
1007};
1008
1009/**
1010 * Gets the list of files stored in the GridFS.
1011 *
1012 * @param {Db} db the database to query.
1013 * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
1014 * @param {Function} callback this will be called after this method executes. Passes null to the first and passes an array of strings containing the names of the files.
1015 * @return {null}
1016 * @api public
1017 */
10181GridStore.list = function(db, rootCollection, options, callback) {
10190 var args = Array.prototype.slice.call(arguments, 1);
10200 callback = args.pop();
10210 rootCollection = args.length ? args.shift() : null;
10220 options = args.length ? args.shift() : {};
1023
1024 // Ensure we have correct values
10250 if(rootCollection != null && typeof rootCollection == 'object') {
10260 options = rootCollection;
10270 rootCollection = null;
1028 }
1029
1030 // Establish read preference
10310 var readPreference = options.readPreference || 'primary';
1032 // Check if we are returning by id not filename
10330 var byId = options['id'] != null ? options['id'] : false;
1034 // Fetch item
10350 var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION;
10360 var items = [];
10370 db.collection((rootCollectionFinal + ".files"), function(err, collection) {
10380 if(err) return callback(err);
1039
10400 collection.find({}, {readPreference:readPreference}, function(err, cursor) {
10410 if(err) return callback(err);
1042
10430 cursor.each(function(err, item) {
10440 if(item != null) {
10450 items.push(byId ? item._id : item.filename);
1046 } else {
10470 callback(err, items);
1048 }
1049 });
1050 });
1051 });
1052};
1053
1054/**
1055 * Reads the contents of a file.
1056 *
1057 * This method has the following signatures
1058 *
1059 * (db, name, callback)
1060 * (db, name, length, callback)
1061 * (db, name, length, offset, callback)
1062 * (db, name, length, offset, options, callback)
1063 *
1064 * @param {Db} db the database to query.
1065 * @param {String} name the name of the file.
1066 * @param {Number} [length] the size of data to read.
1067 * @param {Number} [offset] the offset from the head of the file of which to start reading from.
1068 * @param {Object} [options] the options for the file.
1069 * @param {Function} callback this will be called after this method executes. A string with an error message will be passed to the first parameter when the length and offset combination exceeds the length of the file while an Error object will be passed if other forms of error occured, otherwise, a string is passed. The second parameter will contain the data read if successful or null if an error occured.
1070 * @return {null}
1071 * @api public
1072 */
10731GridStore.read = function(db, name, length, offset, options, callback) {
10740 var args = Array.prototype.slice.call(arguments, 2);
10750 callback = args.pop();
10760 length = args.length ? args.shift() : null;
10770 offset = args.length ? args.shift() : null;
10780 options = args.length ? args.shift() : null;
1079
10800 new GridStore(db, name, "r", options).open(function(err, gridStore) {
10810 if(err) return callback(err);
1082 // Make sure we are not reading out of bounds
10830 if(offset && offset >= gridStore.length) return callback("offset larger than size of file", null);
10840 if(length && length > gridStore.length) return callback("length is larger than the size of the file", null);
10850 if(offset && length && (offset + length) > gridStore.length) return callback("offset and length is larger than the size of the file", null);
1086
10870 if(offset != null) {
10880 gridStore.seek(offset, function(err, gridStore) {
10890 if(err) return callback(err);
10900 gridStore.read(length, callback);
1091 });
1092 } else {
10930 gridStore.read(length, callback);
1094 }
1095 });
1096};
1097
1098/**
1099 * Reads the data of this file.
1100 *
1101 * @param {Db} db the database to query.
1102 * @param {String} name the name of the file.
1103 * @param {String} [separator] the character to be recognized as the newline separator.
1104 * @param {Object} [options] file options.
1105 * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character.
1106 * @return {null}
1107 * @api public
1108 */
11091GridStore.readlines = function(db, name, separator, options, callback) {
11100 var args = Array.prototype.slice.call(arguments, 2);
11110 callback = args.pop();
11120 separator = args.length ? args.shift() : null;
11130 options = args.length ? args.shift() : null;
1114
11150 var finalSeperator = separator == null ? "\n" : separator;
11160 new GridStore(db, name, "r", options).open(function(err, gridStore) {
11170 if(err) return callback(err);
11180 gridStore.readlines(finalSeperator, callback);
1119 });
1120};
1121
1122/**
1123 * Deletes the chunks and metadata information of a file from GridFS.
1124 *
1125 * @param {Db} db the database to interact with.
1126 * @param {String|Array} names the name/names of the files to delete.
1127 * @param {Object} [options] the options for the files.
1128 * @callback {Function} this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
1129 * @return {null}
1130 * @api public
1131 */
11321GridStore.unlink = function(db, names, options, callback) {
11330 var self = this;
11340 var args = Array.prototype.slice.call(arguments, 2);
11350 callback = args.pop();
11360 options = args.length ? args.shift() : null;
1137
11380 if(names.constructor == Array) {
11390 var tc = 0;
11400 for(var i = 0; i < names.length; i++) {
11410 ++tc;
11420 self.unlink(db, names[i], options, function(result) {
11430 if(--tc == 0) {
11440 callback(null, self);
1145 }
1146 });
1147 }
1148 } else {
11490 new GridStore(db, names, "w", options).open(function(err, gridStore) {
11500 if(err) return callback(err);
11510 deleteChunks(gridStore, function(err, result) {
11520 if(err) return callback(err);
11530 gridStore.collection(function(err, collection) {
11540 if(err) return callback(err);
11550 collection.remove({'_id':gridStore.fileId}, {safe:true}, function(err, collection) {
11560 callback(err, self);
1157 });
1158 });
1159 });
1160 });
1161 }
1162};
1163
1164/**
1165 * Returns the current chunksize of the file.
1166 *
1167 * @field chunkSize
1168 * @type {Number}
1169 * @getter
1170 * @setter
1171 * @property return number of bytes in the current chunkSize.
1172 */
11731Object.defineProperty(GridStore.prototype, "chunkSize", { enumerable: true
1174 , get: function () {
11750 return this.internalChunkSize;
1176 }
1177 , set: function(value) {
11780 if(!(this.mode[0] == "w" && this.position == 0 && this.uploadDate == null)) {
11790 this.internalChunkSize = this.internalChunkSize;
1180 } else {
11810 this.internalChunkSize = value;
1182 }
1183 }
1184});
1185
1186/**
1187 * The md5 checksum for this file.
1188 *
1189 * @field md5
1190 * @type {Number}
1191 * @getter
1192 * @setter
1193 * @property return this files md5 checksum.
1194 */
11951Object.defineProperty(GridStore.prototype, "md5", { enumerable: true
1196 , get: function () {
11970 return this.internalMd5;
1198 }
1199});
1200
1201/**
1202 * GridStore Streaming methods
1203 * Handles the correct return of the writeable stream status
1204 * @ignore
1205 */
12061Object.defineProperty(GridStore.prototype, "writable", { enumerable: true
1207 , get: function () {
12080 if(this._writeable == null) {
12090 this._writeable = this.mode != null && this.mode.indexOf("w") != -1;
1210 }
1211 // Return the _writeable
12120 return this._writeable;
1213 }
1214 , set: function(value) {
12150 this._writeable = value;
1216 }
1217});
1218
1219/**
1220 * Handles the correct return of the readable stream status
1221 * @ignore
1222 */
12231Object.defineProperty(GridStore.prototype, "readable", { enumerable: true
1224 , get: function () {
12250 if(this._readable == null) {
12260 this._readable = this.mode != null && this.mode.indexOf("r") != -1;
1227 }
12280 return this._readable;
1229 }
1230 , set: function(value) {
12310 this._readable = value;
1232 }
1233});
1234
12351GridStore.prototype.paused;
1236
1237/**
1238 * Handles the correct setting of encoding for the stream
1239 * @ignore
1240 */
12411GridStore.prototype.setEncoding = fs.ReadStream.prototype.setEncoding;
1242
1243/**
1244 * Handles the end events
1245 * @ignore
1246 */
12471GridStore.prototype.end = function end(data) {
12480 var self = this;
1249 // allow queued data to write before closing
12500 if(!this.writable) return;
12510 this.writable = false;
1252
12530 if(data) {
12540 this._q.push(data);
1255 }
1256
12570 this.on('drain', function () {
12580 self.close(function (err) {
12590 if (err) return _error(self, err);
12600 self.emit('close');
1261 });
1262 });
1263
12640 _flush(self);
1265}
1266
1267/**
1268 * Handles the normal writes to gridstore
1269 * @ignore
1270 */
12711var _writeNormal = function(self, data, close, callback) {
1272 // If we have a buffer write it using the writeBuffer method
12730 if(Buffer.isBuffer(data)) {
12740 return writeBuffer(self, data, close, callback);
1275 } else {
1276 // Wrap the string in a buffer and write
12770 return writeBuffer(self, new Buffer(data, 'binary'), close, callback);
1278 }
1279}
1280
1281/**
1282 * Writes some data. This method will work properly only if initialized with mode "w" or "w+".
1283 *
1284 * @param {String|Buffer} data the data to write.
1285 * @param {Boolean} [close] closes this file after writing if set to true.
1286 * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
1287 * @return {null}
1288 * @api public
1289 */
12901GridStore.prototype.write = function write(data, close, callback) {
1291 // If it's a normal write delegate the call
12920 if(typeof close == 'function' || typeof callback == 'function') {
12930 return _writeNormal(this, data, close, callback);
1294 }
1295
1296 // Otherwise it's a stream write
12970 var self = this;
12980 if (!this.writable) {
12990 throw new Error('GridWriteStream is not writable');
1300 }
1301
1302 // queue data until we open.
13030 if (!this._opened) {
1304 // Set up a queue to save data until gridstore object is ready
13050 this._q = [];
13060 _openStream(self);
13070 this._q.push(data);
13080 return false;
1309 }
1310
1311 // Push data to queue
13120 this._q.push(data);
13130 _flush(this);
1314 // Return write successful
13150 return true;
1316}
1317
1318/**
1319 * Handles the destroy part of a stream
1320 * @ignore
1321 */
13221GridStore.prototype.destroy = function destroy() {
1323 // close and do not emit any more events. queued data is not sent.
13240 if(!this.writable) return;
13250 this.readable = false;
13260 if(this.writable) {
13270 this.writable = false;
13280 this._q.length = 0;
13290 this.emit('close');
1330 }
1331}
1332
1333/**
1334 * Handles the destroySoon part of a stream
1335 * @ignore
1336 */
13371GridStore.prototype.destroySoon = function destroySoon() {
1338 // as soon as write queue is drained, destroy.
1339 // may call destroy immediately if no data is queued.
13400 if(!this._q.length) {
13410 return this.destroy();
1342 }
13430 this._destroying = true;
1344}
1345
1346/**
1347 * Handles the pipe part of the stream
1348 * @ignore
1349 */
13501GridStore.prototype.pipe = function(destination, options) {
13510 var self = this;
1352 // Open the gridstore
13530 this.open(function(err, result) {
13540 if(err) _errorRead(self, err);
13550 if(!self.readable) return;
1356 // Set up the pipe
13570 self._pipe(destination, options);
1358 // Emit the stream is open
13590 self.emit('open');
1360 // Read from the stream
13610 _read(self);
1362 })
1363}
1364
1365/**
1366 * Internal module methods
1367 * @ignore
1368 */
13691var _read = function _read(self) {
13700 if (!self.readable || self.paused || self.reading) {
13710 return;
1372 }
1373
13740 self.reading = true;
13750 var stream = self._stream = self.stream();
13760 stream.paused = self.paused;
1377
13780 stream.on('data', function (data) {
13790 if (self._decoder) {
13800 var str = self._decoder.write(data);
13810 if (str.length) self.emit('data', str);
1382 } else {
13830 self.emit('data', data);
1384 }
1385 });
1386
13870 stream.on('end', function (data) {
13880 self.emit('end', data);
1389 });
1390
13910 stream.on('error', function (data) {
13920 _errorRead(self, data);
1393 });
1394
13950 stream.on('close', function (data) {
13960 self.emit('close', data);
1397 });
1398
13990 self.pause = function () {
1400 // native doesn't always pause.
1401 // bypass its pause() method to hack it
14020 self.paused = stream.paused = true;
1403 }
1404
14050 self.resume = function () {
14060 if(!self.paused) return;
1407
14080 self.paused = false;
14090 stream.resume();
14100 self.readable = stream.readable;
1411 }
1412
14130 self.destroy = function () {
14140 self.readable = false;
14150 stream.destroy();
1416 }
1417}
1418
1419/**
1420 * pause
1421 * @ignore
1422 */
14231GridStore.prototype.pause = function pause () {
1424 // Overridden when the GridStore opens.
14250 this.paused = true;
1426}
1427
1428/**
1429 * resume
1430 * @ignore
1431 */
14321GridStore.prototype.resume = function resume () {
1433 // Overridden when the GridStore opens.
14340 this.paused = false;
1435}
1436
1437/**
1438 * Internal module methods
1439 * @ignore
1440 */
14411var _flush = function _flush(self, _force) {
14420 if (!self._opened) return;
14430 if (!_force && self._flushing) return;
14440 self._flushing = true;
1445
1446 // write the entire q to gridfs
14470 if (!self._q.length) {
14480 self._flushing = false;
14490 self.emit('drain');
1450
14510 if(self._destroying) {
14520 self.destroy();
1453 }
14540 return;
1455 }
1456
14570 self.write(self._q.shift(), function (err, store) {
14580 if (err) return _error(self, err);
14590 self.emit('progress', store.position);
14600 _flush(self, true);
1461 });
1462}
1463
14641var _openStream = function _openStream (self) {
14650 if(self._opening == true) return;
14660 self._opening = true;
1467
1468 // Open the store
14690 self.open(function (err, gridstore) {
14700 if (err) return _error(self, err);
14710 self._opened = true;
14720 self.emit('open');
14730 _flush(self);
1474 });
1475}
1476
14771var _error = function _error(self, err) {
14780 self.destroy();
14790 self.emit('error', err);
1480}
1481
14821var _errorRead = function _errorRead (self, err) {
14830 self.readable = false;
14840 self.emit('error', err);
1485}
1486
1487/**
1488 * @ignore
1489 */
14901var _hasWriteConcern = function(errorOptions) {
14910 return errorOptions == true
1492 || errorOptions.w > 0
1493 || errorOptions.w == 'majority'
1494 || errorOptions.j == true
1495 || errorOptions.journal == true
1496 || errorOptions.fsync == true
1497}
1498
1499/**
1500 * @ignore
1501 */
15021var _setWriteConcernHash = function(options) {
15030 var finalOptions = {};
15040 if(options.w != null) finalOptions.w = options.w;
15050 if(options.journal == true) finalOptions.j = options.journal;
15060 if(options.j == true) finalOptions.j = options.j;
15070 if(options.fsync == true) finalOptions.fsync = options.fsync;
15080 if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout;
15090 return finalOptions;
1510}
1511
1512/**
1513 * @ignore
1514 */
15151var _getWriteConcern = function(self, options, callback) {
1516 // Final options
15170 var finalOptions = {w:1};
15180 options = options || {};
1519 // Local options verification
15200 if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') {
15210 finalOptions = _setWriteConcernHash(options);
15220 } else if(typeof options.safe == "boolean") {
15230 finalOptions = {w: (options.safe ? 1 : 0)};
15240 } else if(options.safe != null && typeof options.safe == 'object') {
15250 finalOptions = _setWriteConcernHash(options.safe);
15260 } else if(self.db.safe.w != null || typeof self.db.safe.j == 'boolean' || typeof self.db.safe.journal == 'boolean' || typeof self.db.safe.fsync == 'boolean') {
15270 finalOptions = _setWriteConcernHash(self.db.safe);
15280 } else if(self.db.options.w != null || typeof self.db.options.j == 'boolean' || typeof self.db.options.journal == 'boolean' || typeof self.db.options.fsync == 'boolean') {
15290 finalOptions = _setWriteConcernHash(self.db.options);
15300 } else if(typeof self.db.safe == "boolean") {
15310 finalOptions = {w: (self.db.safe ? 1 : 0)};
1532 }
1533
1534 // Ensure we don't have an invalid combination of write concerns
15350 if(finalOptions.w < 1
15360 && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowlegement using w < 1 cannot be combined with journal:true or fsync:true");
1537
1538 // Return the options
15390 return finalOptions;
1540}
1541
1542/**
1543 * @ignore
1544 * @api private
1545 */
15461exports.GridStore = GridStore;
1547

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/readstream.js

12%
89
11
78
LineHitsSource
11var Stream = require('stream').Stream,
2 timers = require('timers'),
3 util = require('util');
4
5// Set processor, setImmediate if 0.10 otherwise nextTick
61var processor = require('../utils').processor();
7
8/**
9 * ReadStream
10 *
11 * Returns a stream interface for the **file**.
12 *
13 * Events
14 * - **data** {function(item) {}} the data event triggers when a document is ready.
15 * - **end** {function() {}} the end event triggers when there is no more documents available.
16 * - **close** {function() {}} the close event triggers when the stream is closed.
17 * - **error** {function(err) {}} the error event triggers if an error happens.
18 *
19 * @class Represents a GridFS File Stream.
20 * @param {Boolean} autoclose automatically close file when the stream reaches the end.
21 * @param {GridStore} cursor a cursor object that the stream wraps.
22 * @return {ReadStream}
23 */
241function ReadStream(autoclose, gstore) {
250 if (!(this instanceof ReadStream)) return new ReadStream(autoclose, gstore);
260 Stream.call(this);
27
280 this.autoclose = !!autoclose;
290 this.gstore = gstore;
30
310 this.finalLength = gstore.length - gstore.position;
320 this.completedLength = 0;
330 this.currentChunkNumber = gstore.currentChunk.chunkNumber;
34
350 this.paused = false;
360 this.readable = true;
370 this.pendingChunk = null;
380 this.executing = false;
390 this.destroyed = false;
40
41 // Calculate the number of chunks
420 this.numberOfChunks = Math.ceil(gstore.length/gstore.chunkSize);
43
44 // This seek start position inside the current chunk
450 this.seekStartPosition = gstore.position - (this.currentChunkNumber * gstore.chunkSize);
46
470 var self = this;
480 processor(function() {
490 self._execute();
50 });
51};
52
53/**
54 * Inherit from Stream
55 * @ignore
56 * @api private
57 */
581ReadStream.prototype.__proto__ = Stream.prototype;
59
60/**
61 * Flag stating whether or not this stream is readable.
62 */
631ReadStream.prototype.readable;
64
65/**
66 * Flag stating whether or not this stream is paused.
67 */
681ReadStream.prototype.paused;
69
70/**
71 * @ignore
72 * @api private
73 */
741ReadStream.prototype._execute = function() {
750 if(this.paused === true || this.readable === false) {
760 return;
77 }
78
790 var gstore = this.gstore;
800 var self = this;
81 // Set that we are executing
820 this.executing = true;
83
840 var last = false;
850 var toRead = 0;
86
870 if(gstore.currentChunk.chunkNumber >= (this.numberOfChunks - 1)) {
880 self.executing = false;
890 last = true;
90 }
91
92 // Data setup
930 var data = null;
94
95 // Read a slice (with seek set if none)
960 if(this.seekStartPosition > 0 && (gstore.currentChunk.length() - this.seekStartPosition) > 0) {
970 data = gstore.currentChunk.readSlice(gstore.currentChunk.length() - this.seekStartPosition);
980 this.seekStartPosition = 0;
99 } else {
1000 data = gstore.currentChunk.readSlice(gstore.currentChunk.length());
101 }
102
103 // Return the data
1040 if(data != null && gstore.currentChunk.chunkNumber == self.currentChunkNumber) {
1050 self.currentChunkNumber = self.currentChunkNumber + 1;
1060 self.completedLength += data.length;
1070 self.pendingChunk = null;
1080 self.emit("data", data);
109 }
110
1110 if(last === true) {
1120 self.readable = false;
1130 self.emit("end");
114
1150 if(self.autoclose === true) {
1160 if(gstore.mode[0] == "w") {
1170 gstore.close(function(err, doc) {
1180 if (err) {
1190 console.log("############################## 0")
1200 self.emit("error", err);
1210 return;
122 }
1230 self.readable = false;
1240 self.destroyed = true;
1250 self.emit("close", doc);
126 });
127 } else {
1280 self.readable = false;
1290 self.destroyed = true;
1300 self.emit("close");
131 }
132 }
133 } else {
1340 gstore._nthChunk(gstore.currentChunk.chunkNumber + 1, function(err, chunk) {
1350 if(err) {
1360 self.readable = false;
1370 if(self.listeners("error").length > 0)
1380 self.emit("error", err);
1390 self.executing = false;
1400 return;
141 }
142
1430 self.pendingChunk = chunk;
1440 if(self.paused === true) {
1450 self.executing = false;
1460 return;
147 }
148
1490 gstore.currentChunk = self.pendingChunk;
1500 self._execute();
151 });
152 }
153};
154
155/**
156 * Pauses this stream, then no farther events will be fired.
157 *
158 * @ignore
159 * @api public
160 */
1611ReadStream.prototype.pause = function() {
1620 if(!this.executing) {
1630 this.paused = true;
164 }
165};
166
167/**
168 * Destroys the stream, then no farther events will be fired.
169 *
170 * @ignore
171 * @api public
172 */
1731ReadStream.prototype.destroy = function() {
1740 if(this.destroyed) return;
1750 this.destroyed = true;
1760 this.readable = false;
177 // Emit close event
1780 this.emit("close");
179};
180
181/**
182 * Resumes this stream.
183 *
184 * @ignore
185 * @api public
186 */
1871ReadStream.prototype.resume = function() {
1880 if(this.paused === false || !this.readable) {
1890 return;
190 }
191
1920 this.paused = false;
1930 var self = this;
1940 processor(function() {
1950 self._execute();
196 });
197};
198
1991exports.ReadStream = ReadStream;
200

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/index.js

96%
30
29
1
LineHitsSource
11try {
21 exports.BSONPure = require('bson').BSONPure;
31 exports.BSONNative = require('bson').BSONNative;
4} catch(err) {
5 // do nothing
6}
7
8// export the driver version
91exports.version = require('../../package').version;
10
111[ 'commands/base_command'
12 , 'admin'
13 , 'collection'
14 , 'connection/read_preference'
15 , 'connection/connection'
16 , 'connection/server'
17 , 'connection/mongos'
18 , 'connection/repl_set/repl_set'
19 , 'mongo_client'
20 , 'cursor'
21 , 'db'
22 , 'mongo_client'
23 , 'gridfs/grid'
24 , 'gridfs/chunk'
25 , 'gridfs/gridstore'].forEach(function (path) {
2615 var module = require('./' + path);
2715 for (var i in module) {
2816 exports[i] = module[i];
29 }
30});
31
32// backwards compat
331exports.ReplSetServers = exports.ReplSet;
34// Add BSON Classes
351exports.Binary = require('bson').Binary;
361exports.Code = require('bson').Code;
371exports.DBRef = require('bson').DBRef;
381exports.Double = require('bson').Double;
391exports.Long = require('bson').Long;
401exports.MinKey = require('bson').MinKey;
411exports.MaxKey = require('bson').MaxKey;
421exports.ObjectID = require('bson').ObjectID;
431exports.Symbol = require('bson').Symbol;
441exports.Timestamp = require('bson').Timestamp;
45// Add BSON Parser
461exports.BSON = require('bson').BSONPure.BSON;
47
48// Get the Db object
491var Db = require('./db').Db;
50// Set up the connect function
511var connect = Db.connect;
521var obj = connect;
53// Map all values to the exports value
541for(var name in exports) {
5530 obj[name] = exports[name];
56}
57
58// Add the pure and native backward compatible functions
591exports.pure = exports.native = function() {
600 return obj;
61}
62
63// Map all values to the exports value
641for(var name in exports) {
6532 connect[name] = exports[name];
66}
67
68// Set our exports to be the connect function
691module.exports = connect;
70

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/mongo_client.js

6%
172
11
161
LineHitsSource
11var Db = require('./db').Db
2 , Server = require('./connection/server').Server
3 , Mongos = require('./connection/mongos').Mongos
4 , ReplSet = require('./connection/repl_set/repl_set').ReplSet
5 , ReadPreference = require('./connection/read_preference').ReadPreference
6 , inherits = require('util').inherits
7 , EventEmitter = require('events').EventEmitter
8 , parse = require('./connection/url_parser').parse;
9
10/**
11 * Create a new MongoClient instance.
12 *
13 * Options
14 * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
15 * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
16 * - **fsync**, (Boolean, default:false) write waits for fsync before returning
17 * - **journal**, (Boolean, default:false) write waits for journal sync before returning
18 * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
19 * - **native_parser** {Boolean, default:false}, use c++ bson parser.
20 * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client.
21 * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
22 * - **serializeFunctions** {Boolean, default:false}, serialize functions.
23 * - **raw** {Boolean, default:false}, peform operations using raw bson buffers.
24 * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution.
25 * - **retryMiliSeconds** {Number, default:5000}, number of miliseconds between retries.
26 * - **numberOfRetries** {Number, default:5}, number of retries off connection.
27 * - **bufferMaxEntries** {Boolean, default: -1}, sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited
28 *
29 * Deprecated Options
30 * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
31 *
32 * @class Represents a MongoClient
33 * @param {Object} serverConfig server config object.
34 * @param {Object} [options] additional options for the collection.
35 */
361function MongoClient(serverConfig, options) {
370 if(serverConfig != null) {
380 options = options == null ? {} : options;
39 // If no write concern is set set the default to w:1
400 if(options != null && !options.journal && !options.w && !options.fsync) {
410 options.w = 1;
42 }
43
44 // The internal db instance we are wrapping
450 this._db = new Db('test', serverConfig, options);
46 }
47}
48
49/**
50 * @ignore
51 */
521inherits(MongoClient, EventEmitter);
53
54/**
55 * Connect to MongoDB using a url as documented at
56 *
57 * docs.mongodb.org/manual/reference/connection-string/
58 *
59 * Options
60 * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication
61 * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor**
62 * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor**
63 * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor**
64 * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor**
65 *
66 * @param {String} url connection url for MongoDB.
67 * @param {Object} [options] optional options for insert command
68 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured.
69 * @return {null}
70 * @api public
71 */
721MongoClient.prototype.connect = function(url, options, callback) {
730 var self = this;
74
750 if(typeof options == 'function') {
760 callback = options;
770 options = {};
78 }
79
800 MongoClient.connect(url, options, function(err, db) {
810 if(err) return callback(err, db);
82 // Store internal db instance reference
830 self._db = db;
84 // Emit open and perform callback
850 self.emit("open", err, db);
860 callback(err, db);
87 });
88}
89
90/**
91 * Initialize the database connection.
92 *
93 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the connected mongoclient or null if an error occured.
94 * @return {null}
95 * @api public
96 */
971MongoClient.prototype.open = function(callback) {
98 // Self reference
990 var self = this;
100 // Open the db
1010 this._db.open(function(err, db) {
1020 if(err) return callback(err, null);
103 // Emit open event
1040 self.emit("open", err, db);
105 // Callback
1060 callback(null, self);
107 })
108}
109
110/**
111 * Close the current db connection, including all the child db instances. Emits close event if no callback is provided.
112 *
113 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the close method or null if an error occured.
114 * @return {null}
115 * @api public
116 */
1171MongoClient.prototype.close = function(callback) {
1180 this._db.close(callback);
119}
120
121/**
122 * Create a new Db instance sharing the current socket connections.
123 *
124 * @param {String} dbName the name of the database we want to use.
125 * @return {Db} a db instance using the new database.
126 * @api public
127 */
1281MongoClient.prototype.db = function(dbName) {
1290 return this._db.db(dbName);
130}
131
132/**
133 * Connect to MongoDB using a url as documented at
134 *
135 * docs.mongodb.org/manual/reference/connection-string/
136 *
137 * Options
138 * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication
139 * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor**
140 * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor**
141 * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor**
142 * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor**
143 *
144 * @param {String} url connection url for MongoDB.
145 * @param {Object} [options] optional options for insert command
146 * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured.
147 * @return {null}
148 * @api public
149 */
1501MongoClient.connect = function(url, options, callback) {
1510 var args = Array.prototype.slice.call(arguments, 1);
1520 callback = typeof args[args.length - 1] == 'function' ? args.pop() : null;
1530 options = args.length ? args.shift() : null;
1540 options = options || {};
155
156 // Set default empty server options
1570 var serverOptions = options.server || {};
1580 var mongosOptions = options.mongos || {};
1590 var replSetServersOptions = options.replSet || options.replSetServers || {};
1600 var dbOptions = options.db || {};
161
162 // If callback is null throw an exception
1630 if(callback == null)
1640 throw new Error("no callback function provided");
165
166 // Parse the string
1670 var object = parse(url, options);
168 // Merge in any options for db in options object
1690 if(dbOptions) {
1700 for(var name in dbOptions) object.db_options[name] = dbOptions[name];
171 }
172
173 // Added the url to the options
1740 object.db_options.url = url;
175
176 // Merge in any options for server in options object
1770 if(serverOptions) {
1780 for(var name in serverOptions) object.server_options[name] = serverOptions[name];
179 }
180
181 // Merge in any replicaset server options
1820 if(replSetServersOptions) {
1830 for(var name in replSetServersOptions) object.rs_options[name] = replSetServersOptions[name];
184 }
185
186 // Merge in any replicaset server options
1870 if(mongosOptions) {
1880 for(var name in mongosOptions) object.mongos_options[name] = mongosOptions[name];
189 }
190
191 // We need to ensure that the list of servers are only either direct members or mongos
192 // they cannot be a mix of monogs and mongod's
1930 var totalNumberOfServers = object.servers.length;
1940 var totalNumberOfMongosServers = 0;
1950 var totalNumberOfMongodServers = 0;
1960 var serverConfig = null;
1970 var errorServers = {};
198
199 // Failure modes
2000 if(object.servers.length == 0) throw new Error("connection string must contain at least one seed host");
201
202 // If we have no db setting for the native parser try to set the c++ one first
2030 object.db_options.native_parser = _setNativeParser(object.db_options);
204 // If no auto_reconnect is set, set it to true as default for single servers
2050 if(typeof object.server_options.auto_reconnect != 'boolean') {
2060 object.server_options.auto_reconnect = true;
207 }
208
209 // If we have more than a server, it could be replicaset or mongos list
210 // need to verify that it's one or the other and fail if it's a mix
211 // Connect to all servers and run ismaster
2120 for(var i = 0; i < object.servers.length; i++) {
213 // Set up socket options
2140 var _server_options = {
215 poolSize:1
216 , socketOptions: {
217 connectTimeoutMS:30000
218 , socketTimeoutMS: 30000
219 }
220 , auto_reconnect:false};
221
222 // Ensure we have ssl setup for the servers
2230 if(object.rs_options.ssl) {
2240 _server_options.ssl = object.rs_options.ssl;
2250 _server_options.sslValidate = object.rs_options.sslValidate;
2260 _server_options.sslCA = object.rs_options.sslCA;
2270 _server_options.sslCert = object.rs_options.sslCert;
2280 _server_options.sslKey = object.rs_options.sslKey;
2290 _server_options.sslPass = object.rs_options.sslPass;
2300 } else if(object.server_options.ssl) {
2310 _server_options.ssl = object.server_options.ssl;
2320 _server_options.sslValidate = object.server_options.sslValidate;
2330 _server_options.sslCA = object.server_options.sslCA;
2340 _server_options.sslCert = object.server_options.sslCert;
2350 _server_options.sslKey = object.server_options.sslKey;
2360 _server_options.sslPass = object.server_options.sslPass;
237 }
238
239 // Set up the Server object
2400 var _server = object.servers[i].domain_socket
241 ? new Server(object.servers[i].domain_socket, _server_options)
242 : new Server(object.servers[i].host, object.servers[i].port, _server_options);
243
2440 var connectFunction = function(__server) {
245 // Attempt connect
2460 new Db(object.dbName, __server, {safe:false, native_parser:false}).open(function(err, db) {
247 // Update number of servers
2480 totalNumberOfServers = totalNumberOfServers - 1;
249 // If no error do the correct checks
2500 if(!err) {
251 // Close the connection
2520 db.close(true);
2530 var isMasterDoc = db.serverConfig.isMasterDoc;
254 // Check what type of server we have
2550 if(isMasterDoc.setName) totalNumberOfMongodServers++;
2560 if(isMasterDoc.msg && isMasterDoc.msg == "isdbgrid") totalNumberOfMongosServers++;
257 } else {
2580 errorServers[__server.host + ":" + __server.port] = __server;
259 }
260
2610 if(totalNumberOfServers == 0) {
262 // If we have a mix of mongod and mongos, throw an error
2630 if(totalNumberOfMongosServers > 0 && totalNumberOfMongodServers > 0) {
2640 return process.nextTick(function() {
2650 try {
2660 callback(new Error("cannot combine a list of replicaset seeds and mongos seeds"));
267 } catch (err) {
2680 if(db) db.close();
2690 throw err
270 }
271 })
272 }
273
2740 if(totalNumberOfMongodServers == 0 && object.servers.length == 1) {
2750 var obj = object.servers[0];
2760 serverConfig = obj.domain_socket ?
277 new Server(obj.domain_socket, object.server_options)
278 : new Server(obj.host, obj.port, object.server_options);
2790 } else if(totalNumberOfMongodServers > 0 || totalNumberOfMongosServers > 0) {
2800 var finalServers = object.servers
281 .filter(function(serverObj) {
2820 return errorServers[serverObj.host + ":" + serverObj.port] == null;
283 })
284 .map(function(serverObj) {
2850 return new Server(serverObj.host, serverObj.port, object.server_options);
286 });
287 // Clean out any error servers
2880 errorServers = {};
289 // Set up the final configuration
2900 if(totalNumberOfMongodServers > 0) {
2910 serverConfig = new ReplSet(finalServers, object.rs_options);
292 } else {
2930 serverConfig = new Mongos(finalServers, object.mongos_options);
294 }
295 }
296
2970 if(serverConfig == null) {
2980 return process.nextTick(function() {
2990 try {
3000 callback(new Error("Could not locate any valid servers in initial seed list"));
301 } catch (err) {
3020 if(db) db.close();
3030 throw err
304 }
305 });
306 }
307 // Ensure no firing off open event before we are ready
3080 serverConfig.emitOpen = false;
309 // Set up all options etc and connect to the database
3100 _finishConnecting(serverConfig, object, options, callback)
311 }
312 });
313 }
314
315 // Wrap the context of the call
3160 connectFunction(_server);
317 }
318}
319
3201var _setNativeParser = function(db_options) {
3210 if(typeof db_options.native_parser == 'boolean') return db_options.native_parser;
322
3230 try {
3240 require('bson').BSONNative.BSON;
3250 return true;
326 } catch(err) {
3270 return false;
328 }
329}
330
3311var _finishConnecting = function(serverConfig, object, options, callback) {
332 // Safe settings
3330 var safe = {};
334 // Build the safe parameter if needed
3350 if(object.db_options.journal) safe.j = object.db_options.journal;
3360 if(object.db_options.w) safe.w = object.db_options.w;
3370 if(object.db_options.fsync) safe.fsync = object.db_options.fsync;
3380 if(object.db_options.wtimeoutMS) safe.wtimeout = object.db_options.wtimeoutMS;
339
340 // If we have a read Preference set
3410 if(object.db_options.read_preference) {
3420 var readPreference = new ReadPreference(object.db_options.read_preference);
343 // If we have the tags set up
3440 if(object.db_options.read_preference_tags)
3450 readPreference = new ReadPreference(object.db_options.read_preference, object.db_options.read_preference_tags);
346 // Add the read preference
3470 object.db_options.readPreference = readPreference;
348 }
349
350 // No safe mode if no keys
3510 if(Object.keys(safe).length == 0) safe = false;
352
353 // Add the safe object
3540 object.db_options.safe = safe;
355
356 // Get the socketTimeoutMS
3570 var socketTimeoutMS = object.server_options.socketOptions.socketTimeoutMS || 0;
358
359 // If we have a replset, override with replicaset socket timeout option if available
3600 if(serverConfig instanceof ReplSet) {
3610 socketTimeoutMS = object.rs_options.socketOptions.socketTimeoutMS || socketTimeoutMS;
362 }
363
364 // Set socketTimeout to the same as the connectTimeoutMS or 30 sec
3650 serverConfig.connectTimeoutMS = serverConfig.connectTimeoutMS || 30000;
3660 serverConfig.socketTimeoutMS = serverConfig.connectTimeoutMS;
367
368 // Set up the db options
3690 var db = new Db(object.dbName, serverConfig, object.db_options);
370 // Open the db
3710 db.open(function(err, db){
3720 if(err) {
3730 return process.nextTick(function() {
3740 try {
3750 callback(err, null);
376 } catch (err) {
3770 if(db) db.close();
3780 throw err
379 }
380 });
381 }
382
383 // Reset the socket timeout
3840 serverConfig.socketTimeoutMS = socketTimeoutMS || 0;
385
386 // Set the provided write concern or fall back to w:1 as default
3870 if(db.options !== null && !db.options.safe && !db.options.journal
388 && !db.options.w && !db.options.fsync && typeof db.options.w != 'number'
389 && (db.options.safe == false && object.db_options.url.indexOf("safe=") == -1)) {
3900 db.options.w = 1;
391 }
392
3930 if(err == null && object.auth){
394 // What db to authenticate against
3950 var authentication_db = db;
3960 if(object.db_options && object.db_options.authSource) {
3970 authentication_db = db.db(object.db_options.authSource);
398 }
399
400 // Build options object
4010 var options = {};
4020 if(object.db_options.authMechanism) options.authMechanism = object.db_options.authMechanism;
4030 if(object.db_options.gssapiServiceName) options.gssapiServiceName = object.db_options.gssapiServiceName;
404
405 // Authenticate
4060 authentication_db.authenticate(object.auth.user, object.auth.password, options, function(err, success){
4070 if(success){
4080 process.nextTick(function() {
4090 try {
4100 callback(null, db);
411 } catch (err) {
4120 if(db) db.close();
4130 throw err
414 }
415 });
416 } else {
4170 if(db) db.close();
4180 process.nextTick(function() {
4190 try {
4200 callback(err ? err : new Error('Could not authenticate user ' + auth[0]), null);
421 } catch (err) {
4220 if(db) db.close();
4230 throw err
424 }
425 });
426 }
427 });
428 } else {
4290 process.nextTick(function() {
4300 try {
4310 callback(err, db);
432 } catch (err) {
4330 if(db) db.close();
4340 throw err
435 }
436 })
437 }
438 });
439}
440
4411exports.MongoClient = MongoClient;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js

17%
41
7
34
LineHitsSource
11var Long = require('bson').Long
2 , timers = require('timers');
3
4// Set processor, setImmediate if 0.10 otherwise nextTick
51var processor = require('../utils').processor();
6
7/**
8 Reply message from mongo db
9**/
101var MongoReply = exports.MongoReply = function() {
110 this.documents = [];
120 this.index = 0;
13};
14
151MongoReply.prototype.parseHeader = function(binary_reply, bson) {
16 // Unpack the standard header first
170 this.messageLength = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
180 this.index = this.index + 4;
19 // Fetch the request id for this reply
200 this.requestId = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
210 this.index = this.index + 4;
22 // Fetch the id of the request that triggered the response
230 this.responseTo = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
24 // Skip op-code field
250 this.index = this.index + 4 + 4;
26 // Unpack the reply message
270 this.responseFlag = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
280 this.index = this.index + 4;
29 // Unpack the cursor id (a 64 bit long integer)
300 var low_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
310 this.index = this.index + 4;
320 var high_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
330 this.index = this.index + 4;
340 this.cursorId = new Long(low_bits, high_bits);
35 // Unpack the starting from
360 this.startingFrom = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
370 this.index = this.index + 4;
38 // Unpack the number of objects returned
390 this.numberReturned = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
400 this.index = this.index + 4;
41}
42
431MongoReply.prototype.parseBody = function(binary_reply, bson, raw, callback) {
440 raw = raw == null ? false : raw;
45
460 try {
47 // Let's unpack all the bson documents, deserialize them and store them
480 for(var object_index = 0; object_index < this.numberReturned; object_index++) {
490 var _options = {promoteLongs: bson.promoteLongs};
50
51 // Read the size of the bson object
520 var bsonObjectSize = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
53
54 // If we are storing the raw responses to pipe straight through
550 if(raw) {
56 // Deserialize the object and add to the documents array
570 this.documents.push(binary_reply.slice(this.index, this.index + bsonObjectSize));
58 } else {
59 // Deserialize the object and add to the documents array
600 this.documents.push(bson.deserialize(binary_reply.slice(this.index, this.index + bsonObjectSize), _options));
61 }
62
63 // Adjust binary index to point to next block of binary bson data
640 this.index = this.index + bsonObjectSize;
65 }
66
67 // No error return
680 callback(null);
69 } catch(err) {
700 return callback(err);
71 }
72}
73
741MongoReply.prototype.is_error = function(){
750 if(this.documents.length == 1) {
760 return this.documents[0].ok == 1 ? false : true;
77 }
780 return false;
79};
80
811MongoReply.prototype.error_message = function() {
820 return this.documents.length == 1 && this.documents[0].ok == 1 ? '' : this.documents[0].errmsg;
83};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/scope.js

4%
88
4
84
LineHitsSource
11var Cursor2 = require('./cursor').Cursor
2 , Readable = require('stream').Readable
3 , utils = require('./utils')
4 , inherits = require('util').inherits;
5
61var Cursor = function Cursor(_scope_options, _cursor) {
7 //
8 // Backward compatible methods
90 this.toArray = function(callback) {
100 return _cursor.toArray(callback);
11 }
12
130 this.each = function(callback) {
140 return _cursor.each(callback);
15 }
16
170 this.next = function(callback) {
180 this.nextObject(callback);
19 }
20
210 this.nextObject = function(callback) {
220 return _cursor.nextObject(callback);
23 }
24
250 this.setReadPreference = function(readPreference, callback) {
260 _scope_options.readPreference = {readPreference: readPreference};
270 _cursor.setReadPreference(readPreference, callback);
280 return this;
29 }
30
310 this.batchSize = function(batchSize, callback) {
320 _scope_options.batchSize = batchSize;
330 _cursor.batchSize(_scope_options.batchSize, callback);
340 return this;
35 }
36
370 this.count = function(applySkipLimit, callback) {
380 return _cursor.count(applySkipLimit, callback);
39 }
40
410 this.stream = function(options) {
420 return _cursor.stream(options);
43 }
44
450 this.close = function(callback) {
460 return _cursor.close(callback);
47 }
48
490 this.explain = function(callback) {
500 return _cursor.explain(callback);
51 }
52
530 this.isClosed = function(callback) {
540 return _cursor.isClosed();
55 }
56
570 this.rewind = function() {
580 return _cursor.rewind();
59 }
60
61 // Internal methods
620 this.limit = function(limit, callback) {
630 _cursor.limit(limit, callback);
640 _scope_options.limit = limit;
650 return this;
66 }
67
680 this.skip = function(skip, callback) {
690 _cursor.skip(skip, callback);
700 _scope_options.skip = skip;
710 return this;
72 }
73
740 this.hint = function(hint) {
750 _scope_options.hint = hint;
760 _cursor.hint = _scope_options.hint;
770 return this;
78 }
79
800 this.maxTimeMS = function(maxTimeMS) {
810 _cursor.maxTimeMS(maxTimeMS)
820 _scope_options.maxTimeMS = maxTimeMS;
830 return this;
84 },
85
86 this.sort = function(keyOrList, direction, callback) {
870 _cursor.sort(keyOrList, direction, callback);
880 _scope_options.sort = keyOrList;
890 return this;
90 },
91
92 this.fields = function(fields) {
930 _fields = fields;
940 _cursor.fields = _fields;
950 return this;
96 }
97
98 //
99 // Backward compatible settings
1000 Object.defineProperty(this, "timeout", {
101 get: function() {
1020 return _cursor.timeout;
103 }
104 });
105
1060 Object.defineProperty(this, "read", {
107 get: function() {
1080 return _cursor.read;
109 }
110 });
111
1120 Object.defineProperty(this, "items", {
113 get: function() {
1140 return _cursor.items;
115 }
116 });
117}
118
1191var Scope = function(collection, _selector, _fields, _scope_options) {
1200 var self = this;
121
122 // Ensure we have at least an empty cursor options object
1230 _scope_options = _scope_options || {};
1240 var _write_concern = _scope_options.write_concern || null;
125
126 // Ensure default read preference
1270 if(!_scope_options.readPreference) _scope_options.readPreference = {readPreference: 'primary'};
128
129 // Set up the cursor
1300 var _cursor = new Cursor2(
131 collection.db, collection, _selector
132 , _fields, _scope_options
133 );
134
135 // Write branch options
1360 var writeOptions = {
137 insert: function(documents, callback) {
138 // Merge together options
1390 var options = _write_concern || {};
140 // Execute insert
1410 collection.insert(documents, options, callback);
142 },
143
144 save: function(document, callback) {
145 // Merge together options
1460 var save_options = _write_concern || {};
147 // Execute save
1480 collection.save(document, save_options, function(err, result) {
1490 if(typeof result == 'number' && result == 1) {
1500 return callback(null, document);
151 }
152
1530 return callback(null, document);
154 });
155 },
156
157 find: function(selector) {
1580 _selector = selector;
1590 return writeOptions;
160 },
161
162 //
163 // Update is implicit multiple document update
164 update: function(operations, callback) {
165 // Merge together options
1660 var update_options = _write_concern || {};
167
168 // Set up options, multi is default operation
1690 update_options.multi = _scope_options.multi ? _scope_options.multi : true;
1700 if(_scope_options.upsert) update_options.upsert = _scope_options.upsert;
171
172 // Execute options
1730 collection.update(_selector, operations, update_options, function(err, result, obj) {
1740 callback(err, obj);
175 });
176 },
177 }
178
179 // Set write concern
1800 this.withWriteConcern = function(write_concern) {
181 // Save the current write concern to the Scope
1820 _scope_options.write_concern = write_concern;
1830 _write_concern = write_concern;
184 // Only allow legal options
1850 return writeOptions;
186 }
187
188 // Start find
1890 this.find = function(selector, options) {
190 // Save the current selector
1910 _selector = selector;
192 // Set the cursor
1930 _cursor.selector = selector;
194 // Return only legal read options
1950 return new Cursor(_scope_options, _cursor);
196 }
197}
198
1991exports.Scope = Scope;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/lib/mongodb/utils.js

27%
84
23
61
LineHitsSource
11var timers = require('timers');
2
3/**
4 * Sort functions, Normalize and prepare sort parameters
5 */
61var formatSortValue = exports.formatSortValue = function(sortDirection) {
70 var value = ("" + sortDirection).toLowerCase();
8
90 switch (value) {
10 case 'ascending':
11 case 'asc':
12 case '1':
130 return 1;
14 case 'descending':
15 case 'desc':
16 case '-1':
170 return -1;
18 default:
190 throw new Error("Illegal sort clause, must be of the form "
20 + "[['field1', '(ascending|descending)'], "
21 + "['field2', '(ascending|descending)']]");
22 }
23};
24
251var formattedOrderClause = exports.formattedOrderClause = function(sortValue) {
260 var orderBy = {};
27
280 if (Array.isArray(sortValue)) {
290 for(var i = 0; i < sortValue.length; i++) {
300 if(sortValue[i].constructor == String) {
310 orderBy[sortValue[i]] = 1;
32 } else {
330 orderBy[sortValue[i][0]] = formatSortValue(sortValue[i][1]);
34 }
35 }
360 } else if(Object.prototype.toString.call(sortValue) === '[object Object]') {
370 orderBy = sortValue;
380 } else if (sortValue.constructor == String) {
390 orderBy[sortValue] = 1;
40 } else {
410 throw new Error("Illegal sort clause, must be of the form " +
42 "[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]");
43 }
44
450 return orderBy;
46};
47
481exports.encodeInt = function(value) {
490 var buffer = new Buffer(4);
500 buffer[3] = (value >> 24) & 0xff;
510 buffer[2] = (value >> 16) & 0xff;
520 buffer[1] = (value >> 8) & 0xff;
530 buffer[0] = value & 0xff;
540 return buffer;
55}
56
571exports.encodeIntInPlace = function(value, buffer, index) {
580 buffer[index + 3] = (value >> 24) & 0xff;
590 buffer[index + 2] = (value >> 16) & 0xff;
600 buffer[index + 1] = (value >> 8) & 0xff;
610 buffer[index] = value & 0xff;
62}
63
641exports.encodeCString = function(string) {
650 var buf = new Buffer(string, 'utf8');
660 return [buf, new Buffer([0])];
67}
68
691exports.decodeUInt32 = function(array, index) {
700 return array[index] | array[index + 1] << 8 | array[index + 2] << 16 | array[index + 3] << 24;
71}
72
73// Decode the int
741exports.decodeUInt8 = function(array, index) {
750 return array[index];
76}
77
78/**
79 * Context insensitive type checks
80 */
81
821var toString = Object.prototype.toString;
83
841exports.isObject = function (arg) {
850 return '[object Object]' == toString.call(arg)
86}
87
881exports.isArray = function (arg) {
890 return Array.isArray(arg) ||
90 'object' == typeof arg && '[object Array]' == toString.call(arg)
91}
92
931exports.isDate = function (arg) {
940 return 'object' == typeof arg && '[object Date]' == toString.call(arg)
95}
96
971exports.isRegExp = function (arg) {
980 return 'object' == typeof arg && '[object RegExp]' == toString.call(arg)
99}
100
101/**
102 * Wrap a Mongo error document in an Error instance
103 * @ignore
104 * @api private
105 */
1061var toError = function(error) {
1070 if (error instanceof Error) return error;
108
1090 var msg = error.err || error.errmsg || error.errMessage || error;
1100 var e = new Error(msg);
1110 e.name = 'MongoError';
112
113 // Get all object keys
1140 var keys = typeof error == 'object'
115 ? Object.keys(error)
116 : [];
117
1180 for(var i = 0; i < keys.length; i++) {
1190 e[keys[i]] = error[keys[i]];
120 }
121
1220 return e;
123}
1241exports.toError = toError;
125
126/**
127 * Convert a single level object to an array
128 * @ignore
129 * @api private
130 */
1311exports.objectToArray = function(object) {
1320 var list = [];
133
1340 for(var name in object) {
1350 list.push(object[name])
136 }
137
1380 return list;
139}
140
141/**
142 * Handle single command document return
143 * @ignore
144 * @api private
145 */
1461exports.handleSingleCommandResultReturn = function(override_value_true, override_value_false, callback) {
1470 return function(err, result, connection) {
1480 if(err && typeof callback == 'function') return callback(err, null);
1490 if(!result || !result.documents || result.documents.length == 0)
1500 if(typeof callback == 'function') return callback(toError("command failed to return results"), null)
1510 if(result && result.documents[0].ok == 1) {
1520 if(override_value_true) return callback(null, override_value_true)
1530 if(typeof callback == 'function') return callback(null, result.documents[0]);
154 }
155
156 // Return the error from the document
1570 if(typeof callback == 'function') return callback(toError(result.documents[0]), override_value_false);
158 }
159}
160
161/**
162 * Return correct processor
163 * @ignore
164 * @api private
165 */
1661exports.processor = function() {
167 // Set processor, setImmediate if 0.10 otherwise nextTick
16810 process.maxTickDepth = Infinity;
169 // Only use nextTick
17010 return process.nextTick;
171}
172
173/**
174 * Allow setting the socketTimeoutMS on all connections
175 * to work around issues such as secondaries blocking due to compaction
176 *
177 * @ignore
178 * @api private
179 */
1801exports.setSocketTimeoutProperty = function(self, options) {
1811 Object.defineProperty(self, "socketTimeoutMS", {
182 enumerable: true
1830 , get: function () { return options.socketTimeoutMS; }
184 , set: function (value) {
185 // Set the socket timeoutMS value
1860 options.socketTimeoutMS = value;
187
188 // Get all the connections
1890 var connections = self.allRawConnections();
1900 for(var i = 0; i < connections.length; i++) {
1910 connections[i].socketTimeoutMS = value;
192 }
193 }
194 });
195}
196
1971exports.hasWriteCommands = function(connection) {
1980 return connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasWriteCommands;
199}
200
201
202
203

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/binary.js

18%
121
22
99
LineHitsSource
1/**
2 * Module dependencies.
3 */
41if(typeof window === 'undefined') {
51 var Buffer = require('buffer').Buffer; // TODO just use global Buffer
6}
7
8// Binary default subtype
91var BSON_BINARY_SUBTYPE_DEFAULT = 0;
10
11/**
12 * @ignore
13 * @api private
14 */
151var writeStringToArray = function(data) {
16 // Create a buffer
170 var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(data.length)) : new Array(data.length);
18 // Write the content to the buffer
190 for(var i = 0; i < data.length; i++) {
200 buffer[i] = data.charCodeAt(i);
21 }
22 // Write the string to the buffer
230 return buffer;
24}
25
26/**
27 * Convert Array ot Uint8Array to Binary String
28 *
29 * @ignore
30 * @api private
31 */
321var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) {
330 var result = "";
340 for(var i = startIndex; i < endIndex; i++) {
350 result = result + String.fromCharCode(byteArray[i]);
36 }
370 return result;
38};
39
40/**
41 * A class representation of the BSON Binary type.
42 *
43 * Sub types
44 * - **BSON.BSON_BINARY_SUBTYPE_DEFAULT**, default BSON type.
45 * - **BSON.BSON_BINARY_SUBTYPE_FUNCTION**, BSON function type.
46 * - **BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY**, BSON byte array type.
47 * - **BSON.BSON_BINARY_SUBTYPE_UUID**, BSON uuid type.
48 * - **BSON.BSON_BINARY_SUBTYPE_MD5**, BSON md5 type.
49 * - **BSON.BSON_BINARY_SUBTYPE_USER_DEFINED**, BSON user defined type.
50 *
51 * @class Represents the Binary BSON type.
52 * @param {Buffer} buffer a buffer object containing the binary data.
53 * @param {Number} [subType] the option binary type.
54 * @return {Grid}
55 */
561function Binary(buffer, subType) {
570 if(!(this instanceof Binary)) return new Binary(buffer, subType);
58
590 this._bsontype = 'Binary';
60
610 if(buffer instanceof Number) {
620 this.sub_type = buffer;
630 this.position = 0;
64 } else {
650 this.sub_type = subType == null ? BSON_BINARY_SUBTYPE_DEFAULT : subType;
660 this.position = 0;
67 }
68
690 if(buffer != null && !(buffer instanceof Number)) {
70 // Only accept Buffer, Uint8Array or Arrays
710 if(typeof buffer == 'string') {
72 // Different ways of writing the length of the string for the different types
730 if(typeof Buffer != 'undefined') {
740 this.buffer = new Buffer(buffer);
750 } else if(typeof Uint8Array != 'undefined' || (Object.prototype.toString.call(buffer) == '[object Array]')) {
760 this.buffer = writeStringToArray(buffer);
77 } else {
780 throw new Error("only String, Buffer, Uint8Array or Array accepted");
79 }
80 } else {
810 this.buffer = buffer;
82 }
830 this.position = buffer.length;
84 } else {
850 if(typeof Buffer != 'undefined') {
860 this.buffer = new Buffer(Binary.BUFFER_SIZE);
870 } else if(typeof Uint8Array != 'undefined'){
880 this.buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE));
89 } else {
900 this.buffer = new Array(Binary.BUFFER_SIZE);
91 }
92 // Set position to start of buffer
930 this.position = 0;
94 }
95};
96
97/**
98 * Updates this binary with byte_value.
99 *
100 * @param {Character} byte_value a single byte we wish to write.
101 * @api public
102 */
1031Binary.prototype.put = function put(byte_value) {
104 // If it's a string and a has more than one character throw an error
1050 if(byte_value['length'] != null && typeof byte_value != 'number' && byte_value.length != 1) throw new Error("only accepts single character String, Uint8Array or Array");
1060 if(typeof byte_value != 'number' && byte_value < 0 || byte_value > 255) throw new Error("only accepts number in a valid unsigned byte range 0-255");
107
108 // Decode the byte value once
1090 var decoded_byte = null;
1100 if(typeof byte_value == 'string') {
1110 decoded_byte = byte_value.charCodeAt(0);
1120 } else if(byte_value['length'] != null) {
1130 decoded_byte = byte_value[0];
114 } else {
1150 decoded_byte = byte_value;
116 }
117
1180 if(this.buffer.length > this.position) {
1190 this.buffer[this.position++] = decoded_byte;
120 } else {
1210 if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) {
122 // Create additional overflow buffer
1230 var buffer = new Buffer(Binary.BUFFER_SIZE + this.buffer.length);
124 // Combine the two buffers together
1250 this.buffer.copy(buffer, 0, 0, this.buffer.length);
1260 this.buffer = buffer;
1270 this.buffer[this.position++] = decoded_byte;
128 } else {
1290 var buffer = null;
130 // Create a new buffer (typed or normal array)
1310 if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') {
1320 buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE + this.buffer.length));
133 } else {
1340 buffer = new Array(Binary.BUFFER_SIZE + this.buffer.length);
135 }
136
137 // We need to copy all the content to the new array
1380 for(var i = 0; i < this.buffer.length; i++) {
1390 buffer[i] = this.buffer[i];
140 }
141
142 // Reassign the buffer
1430 this.buffer = buffer;
144 // Write the byte
1450 this.buffer[this.position++] = decoded_byte;
146 }
147 }
148};
149
150/**
151 * Writes a buffer or string to the binary.
152 *
153 * @param {Buffer|String} string a string or buffer to be written to the Binary BSON object.
154 * @param {Number} offset specify the binary of where to write the content.
155 * @api public
156 */
1571Binary.prototype.write = function write(string, offset) {
1580 offset = typeof offset == 'number' ? offset : this.position;
159
160 // If the buffer is to small let's extend the buffer
1610 if(this.buffer.length < offset + string.length) {
1620 var buffer = null;
163 // If we are in node.js
1640 if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) {
1650 buffer = new Buffer(this.buffer.length + string.length);
1660 this.buffer.copy(buffer, 0, 0, this.buffer.length);
1670 } else if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') {
168 // Create a new buffer
1690 buffer = new Uint8Array(new ArrayBuffer(this.buffer.length + string.length))
170 // Copy the content
1710 for(var i = 0; i < this.position; i++) {
1720 buffer[i] = this.buffer[i];
173 }
174 }
175
176 // Assign the new buffer
1770 this.buffer = buffer;
178 }
179
1800 if(typeof Buffer != 'undefined' && Buffer.isBuffer(string) && Buffer.isBuffer(this.buffer)) {
1810 string.copy(this.buffer, offset, 0, string.length);
1820 this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position;
183 // offset = string.length
1840 } else if(typeof Buffer != 'undefined' && typeof string == 'string' && Buffer.isBuffer(this.buffer)) {
1850 this.buffer.write(string, 'binary', offset);
1860 this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position;
187 // offset = string.length;
1880 } else if(Object.prototype.toString.call(string) == '[object Uint8Array]'
189 || Object.prototype.toString.call(string) == '[object Array]' && typeof string != 'string') {
1900 for(var i = 0; i < string.length; i++) {
1910 this.buffer[offset++] = string[i];
192 }
193
1940 this.position = offset > this.position ? offset : this.position;
1950 } else if(typeof string == 'string') {
1960 for(var i = 0; i < string.length; i++) {
1970 this.buffer[offset++] = string.charCodeAt(i);
198 }
199
2000 this.position = offset > this.position ? offset : this.position;
201 }
202};
203
204/**
205 * Reads **length** bytes starting at **position**.
206 *
207 * @param {Number} position read from the given position in the Binary.
208 * @param {Number} length the number of bytes to read.
209 * @return {Buffer}
210 * @api public
211 */
2121Binary.prototype.read = function read(position, length) {
2130 length = length && length > 0
214 ? length
215 : this.position;
216
217 // Let's return the data based on the type we have
2180 if(this.buffer['slice']) {
2190 return this.buffer.slice(position, position + length);
220 } else {
221 // Create a buffer to keep the result
2220 var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(length)) : new Array(length);
2230 for(var i = 0; i < length; i++) {
2240 buffer[i] = this.buffer[position++];
225 }
226 }
227 // Return the buffer
2280 return buffer;
229};
230
231/**
232 * Returns the value of this binary as a string.
233 *
234 * @return {String}
235 * @api public
236 */
2371Binary.prototype.value = function value(asRaw) {
2380 asRaw = asRaw == null ? false : asRaw;
239
240 // If it's a node.js buffer object
2410 if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) {
2420 return asRaw ? this.buffer.slice(0, this.position) : this.buffer.toString('binary', 0, this.position);
243 } else {
2440 if(asRaw) {
245 // we support the slice command use it
2460 if(this.buffer['slice'] != null) {
2470 return this.buffer.slice(0, this.position);
248 } else {
249 // Create a new buffer to copy content to
2500 var newBuffer = Object.prototype.toString.call(this.buffer) == '[object Uint8Array]' ? new Uint8Array(new ArrayBuffer(this.position)) : new Array(this.position);
251 // Copy content
2520 for(var i = 0; i < this.position; i++) {
2530 newBuffer[i] = this.buffer[i];
254 }
255 // Return the buffer
2560 return newBuffer;
257 }
258 } else {
2590 return convertArraytoUtf8BinaryString(this.buffer, 0, this.position);
260 }
261 }
262};
263
264/**
265 * Length.
266 *
267 * @return {Number} the length of the binary.
268 * @api public
269 */
2701Binary.prototype.length = function length() {
2710 return this.position;
272};
273
274/**
275 * @ignore
276 * @api private
277 */
2781Binary.prototype.toJSON = function() {
2790 return this.buffer != null ? this.buffer.toString('base64') : '';
280}
281
282/**
283 * @ignore
284 * @api private
285 */
2861Binary.prototype.toString = function(format) {
2870 return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : '';
288}
289
2901Binary.BUFFER_SIZE = 256;
291
292/**
293 * Default BSON type
294 *
295 * @classconstant SUBTYPE_DEFAULT
296 **/
2971Binary.SUBTYPE_DEFAULT = 0;
298/**
299 * Function BSON type
300 *
301 * @classconstant SUBTYPE_DEFAULT
302 **/
3031Binary.SUBTYPE_FUNCTION = 1;
304/**
305 * Byte Array BSON type
306 *
307 * @classconstant SUBTYPE_DEFAULT
308 **/
3091Binary.SUBTYPE_BYTE_ARRAY = 2;
310/**
311 * OLD UUID BSON type
312 *
313 * @classconstant SUBTYPE_DEFAULT
314 **/
3151Binary.SUBTYPE_UUID_OLD = 3;
316/**
317 * UUID BSON type
318 *
319 * @classconstant SUBTYPE_DEFAULT
320 **/
3211Binary.SUBTYPE_UUID = 4;
322/**
323 * MD5 BSON type
324 *
325 * @classconstant SUBTYPE_DEFAULT
326 **/
3271Binary.SUBTYPE_MD5 = 5;
328/**
329 * User BSON type
330 *
331 * @classconstant SUBTYPE_DEFAULT
332 **/
3331Binary.SUBTYPE_USER_DEFINED = 128;
334
335/**
336 * Expose.
337 */
3381exports.Binary = Binary;
339
340

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js

22%
198
45
153
LineHitsSource
1/**
2 * Binary Parser.
3 * Jonas Raoni Soares Silva
4 * http://jsfromhell.com/classes/binary-parser [v1.0]
5 */
61var chr = String.fromCharCode;
7
81var maxBits = [];
91for (var i = 0; i < 64; i++) {
1064 maxBits[i] = Math.pow(2, i);
11}
12
131function BinaryParser (bigEndian, allowExceptions) {
140 if(!(this instanceof BinaryParser)) return new BinaryParser(bigEndian, allowExceptions);
15
160 this.bigEndian = bigEndian;
170 this.allowExceptions = allowExceptions;
18};
19
201BinaryParser.warn = function warn (msg) {
210 if (this.allowExceptions) {
220 throw new Error(msg);
23 }
24
250 return 1;
26};
27
281BinaryParser.decodeFloat = function decodeFloat (data, precisionBits, exponentBits) {
290 var b = new this.Buffer(this.bigEndian, data);
30
310 b.checkBuffer(precisionBits + exponentBits + 1);
32
330 var bias = maxBits[exponentBits - 1] - 1
34 , signal = b.readBits(precisionBits + exponentBits, 1)
35 , exponent = b.readBits(precisionBits, exponentBits)
36 , significand = 0
37 , divisor = 2
38 , curByte = b.buffer.length + (-precisionBits >> 3) - 1;
39
400 do {
410 for (var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 );
42 } while (precisionBits -= startBit);
43
440 return exponent == ( bias << 1 ) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity : ( 1 + signal * -2 ) * ( exponent || significand ? !exponent ? Math.pow( 2, -bias + 1 ) * significand : Math.pow( 2, exponent - bias ) * ( 1 + significand ) : 0 );
45};
46
471BinaryParser.decodeInt = function decodeInt (data, bits, signed, forceBigEndian) {
480 var b = new this.Buffer(this.bigEndian || forceBigEndian, data)
49 , x = b.readBits(0, bits)
50 , max = maxBits[bits]; //max = Math.pow( 2, bits );
51
520 return signed && x >= max / 2
53 ? x - max
54 : x;
55};
56
571BinaryParser.encodeFloat = function encodeFloat (data, precisionBits, exponentBits) {
580 var bias = maxBits[exponentBits - 1] - 1
59 , minExp = -bias + 1
60 , maxExp = bias
61 , minUnnormExp = minExp - precisionBits
62 , n = parseFloat(data)
63 , status = isNaN(n) || n == -Infinity || n == +Infinity ? n : 0
64 , exp = 0
65 , len = 2 * bias + 1 + precisionBits + 3
66 , bin = new Array(len)
67 , signal = (n = status !== 0 ? 0 : n) < 0
68 , intPart = Math.floor(n = Math.abs(n))
69 , floatPart = n - intPart
70 , lastBit
71 , rounded
72 , result
73 , i
74 , j;
75
760 for (i = len; i; bin[--i] = 0);
77
780 for (i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2));
79
800 for (i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0 ) && --floatPart);
81
820 for (i = -1; ++i < len && !bin[i];);
83
840 if (bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]) {
850 if (!(rounded = bin[lastBit])) {
860 for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]);
87 }
88
890 for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0));
90 }
91
920 for (i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];);
93
940 if ((exp = bias + 1 - i) >= minExp && exp <= maxExp) {
950 ++i;
960 } else if (exp < minExp) {
970 exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow");
980 i = bias + 1 - (exp = minExp - 1);
99 }
100
1010 if (intPart || status !== 0) {
1020 this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status);
1030 exp = maxExp + 1;
1040 i = bias + 2;
105
1060 if (status == -Infinity) {
1070 signal = 1;
1080 } else if (isNaN(status)) {
1090 bin[i] = 1;
110 }
111 }
112
1130 for (n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1);
114
1150 for (n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; i; j = (j + 1) % 8) {
1160 n += (1 << j) * result.charAt(--i);
1170 if (j == 7) {
1180 r[r.length] = String.fromCharCode(n);
1190 n = 0;
120 }
121 }
122
1230 r[r.length] = n
124 ? String.fromCharCode(n)
125 : "";
126
1270 return (this.bigEndian ? r.reverse() : r).join("");
128};
129
1301BinaryParser.encodeInt = function encodeInt (data, bits, signed, forceBigEndian) {
1310 var max = maxBits[bits];
132
1330 if (data >= max || data < -(max / 2)) {
1340 this.warn("encodeInt::overflow");
1350 data = 0;
136 }
137
1380 if (data < 0) {
1390 data += max;
140 }
141
1420 for (var r = []; data; r[r.length] = String.fromCharCode(data % 256), data = Math.floor(data / 256));
143
1440 for (bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0");
145
1460 return ((this.bigEndian || forceBigEndian) ? r.reverse() : r).join("");
147};
148
1491BinaryParser.toSmall = function( data ){ return this.decodeInt( data, 8, true ); };
1501BinaryParser.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); };
1511BinaryParser.toByte = function( data ){ return this.decodeInt( data, 8, false ); };
1521BinaryParser.fromByte = function( data ){ return this.encodeInt( data, 8, false ); };
1531BinaryParser.toShort = function( data ){ return this.decodeInt( data, 16, true ); };
1541BinaryParser.fromShort = function( data ){ return this.encodeInt( data, 16, true ); };
1551BinaryParser.toWord = function( data ){ return this.decodeInt( data, 16, false ); };
1561BinaryParser.fromWord = function( data ){ return this.encodeInt( data, 16, false ); };
1571BinaryParser.toInt = function( data ){ return this.decodeInt( data, 32, true ); };
1581BinaryParser.fromInt = function( data ){ return this.encodeInt( data, 32, true ); };
1591BinaryParser.toLong = function( data ){ return this.decodeInt( data, 64, true ); };
1601BinaryParser.fromLong = function( data ){ return this.encodeInt( data, 64, true ); };
1611BinaryParser.toDWord = function( data ){ return this.decodeInt( data, 32, false ); };
1621BinaryParser.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); };
1631BinaryParser.toQWord = function( data ){ return this.decodeInt( data, 64, true ); };
1641BinaryParser.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); };
1651BinaryParser.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); };
1661BinaryParser.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); };
1671BinaryParser.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); };
1681BinaryParser.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); };
169
170// Factor out the encode so it can be shared by add_header and push_int32
1711BinaryParser.encode_int32 = function encode_int32 (number, asArray) {
1720 var a, b, c, d, unsigned;
1730 unsigned = (number < 0) ? (number + 0x100000000) : number;
1740 a = Math.floor(unsigned / 0xffffff);
1750 unsigned &= 0xffffff;
1760 b = Math.floor(unsigned / 0xffff);
1770 unsigned &= 0xffff;
1780 c = Math.floor(unsigned / 0xff);
1790 unsigned &= 0xff;
1800 d = Math.floor(unsigned);
1810 return asArray ? [chr(a), chr(b), chr(c), chr(d)] : chr(a) + chr(b) + chr(c) + chr(d);
182};
183
1841BinaryParser.encode_int64 = function encode_int64 (number) {
1850 var a, b, c, d, e, f, g, h, unsigned;
1860 unsigned = (number < 0) ? (number + 0x10000000000000000) : number;
1870 a = Math.floor(unsigned / 0xffffffffffffff);
1880 unsigned &= 0xffffffffffffff;
1890 b = Math.floor(unsigned / 0xffffffffffff);
1900 unsigned &= 0xffffffffffff;
1910 c = Math.floor(unsigned / 0xffffffffff);
1920 unsigned &= 0xffffffffff;
1930 d = Math.floor(unsigned / 0xffffffff);
1940 unsigned &= 0xffffffff;
1950 e = Math.floor(unsigned / 0xffffff);
1960 unsigned &= 0xffffff;
1970 f = Math.floor(unsigned / 0xffff);
1980 unsigned &= 0xffff;
1990 g = Math.floor(unsigned / 0xff);
2000 unsigned &= 0xff;
2010 h = Math.floor(unsigned);
2020 return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h);
203};
204
205/**
206 * UTF8 methods
207 */
208
209// Take a raw binary string and return a utf8 string
2101BinaryParser.decode_utf8 = function decode_utf8 (binaryStr) {
2110 var len = binaryStr.length
212 , decoded = ''
213 , i = 0
214 , c = 0
215 , c1 = 0
216 , c2 = 0
217 , c3;
218
2190 while (i < len) {
2200 c = binaryStr.charCodeAt(i);
2210 if (c < 128) {
2220 decoded += String.fromCharCode(c);
2230 i++;
2240 } else if ((c > 191) && (c < 224)) {
2250 c2 = binaryStr.charCodeAt(i+1);
2260 decoded += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
2270 i += 2;
228 } else {
2290 c2 = binaryStr.charCodeAt(i+1);
2300 c3 = binaryStr.charCodeAt(i+2);
2310 decoded += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
2320 i += 3;
233 }
234 }
235
2360 return decoded;
237};
238
239// Encode a cstring
2401BinaryParser.encode_cstring = function encode_cstring (s) {
2410 return unescape(encodeURIComponent(s)) + BinaryParser.fromByte(0);
242};
243
244// Take a utf8 string and return a binary string
2451BinaryParser.encode_utf8 = function encode_utf8 (s) {
2460 var a = ""
247 , c;
248
2490 for (var n = 0, len = s.length; n < len; n++) {
2500 c = s.charCodeAt(n);
251
2520 if (c < 128) {
2530 a += String.fromCharCode(c);
2540 } else if ((c > 127) && (c < 2048)) {
2550 a += String.fromCharCode((c>>6) | 192) ;
2560 a += String.fromCharCode((c&63) | 128);
257 } else {
2580 a += String.fromCharCode((c>>12) | 224);
2590 a += String.fromCharCode(((c>>6) & 63) | 128);
2600 a += String.fromCharCode((c&63) | 128);
261 }
262 }
263
2640 return a;
265};
266
2671BinaryParser.hprint = function hprint (s) {
2680 var number;
269
2700 for (var i = 0, len = s.length; i < len; i++) {
2710 if (s.charCodeAt(i) < 32) {
2720 number = s.charCodeAt(i) <= 15
273 ? "0" + s.charCodeAt(i).toString(16)
274 : s.charCodeAt(i).toString(16);
2750 process.stdout.write(number + " ")
276 } else {
2770 number = s.charCodeAt(i) <= 15
278 ? "0" + s.charCodeAt(i).toString(16)
279 : s.charCodeAt(i).toString(16);
2800 process.stdout.write(number + " ")
281 }
282 }
283
2840 process.stdout.write("\n\n");
285};
286
2871BinaryParser.ilprint = function hprint (s) {
2880 var number;
289
2900 for (var i = 0, len = s.length; i < len; i++) {
2910 if (s.charCodeAt(i) < 32) {
2920 number = s.charCodeAt(i) <= 15
293 ? "0" + s.charCodeAt(i).toString(10)
294 : s.charCodeAt(i).toString(10);
295
2960 require('util').debug(number+' : ');
297 } else {
2980 number = s.charCodeAt(i) <= 15
299 ? "0" + s.charCodeAt(i).toString(10)
300 : s.charCodeAt(i).toString(10);
3010 require('util').debug(number+' : '+ s.charAt(i));
302 }
303 }
304};
305
3061BinaryParser.hlprint = function hprint (s) {
3070 var number;
308
3090 for (var i = 0, len = s.length; i < len; i++) {
3100 if (s.charCodeAt(i) < 32) {
3110 number = s.charCodeAt(i) <= 15
312 ? "0" + s.charCodeAt(i).toString(16)
313 : s.charCodeAt(i).toString(16);
3140 require('util').debug(number+' : ');
315 } else {
3160 number = s.charCodeAt(i) <= 15
317 ? "0" + s.charCodeAt(i).toString(16)
318 : s.charCodeAt(i).toString(16);
3190 require('util').debug(number+' : '+ s.charAt(i));
320 }
321 }
322};
323
324/**
325 * BinaryParser buffer constructor.
326 */
3271function BinaryParserBuffer (bigEndian, buffer) {
3280 this.bigEndian = bigEndian || 0;
3290 this.buffer = [];
3300 this.setBuffer(buffer);
331};
332
3331BinaryParserBuffer.prototype.setBuffer = function setBuffer (data) {
3340 var l, i, b;
335
3360 if (data) {
3370 i = l = data.length;
3380 b = this.buffer = new Array(l);
3390 for (; i; b[l - i] = data.charCodeAt(--i));
3400 this.bigEndian && b.reverse();
341 }
342};
343
3441BinaryParserBuffer.prototype.hasNeededBits = function hasNeededBits (neededBits) {
3450 return this.buffer.length >= -(-neededBits >> 3);
346};
347
3481BinaryParserBuffer.prototype.checkBuffer = function checkBuffer (neededBits) {
3490 if (!this.hasNeededBits(neededBits)) {
3500 throw new Error("checkBuffer::missing bytes");
351 }
352};
353
3541BinaryParserBuffer.prototype.readBits = function readBits (start, length) {
355 //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni)
356
3570 function shl (a, b) {
3580 for (; b--; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1);
3590 return a;
360 }
361
3620 if (start < 0 || length <= 0) {
3630 return 0;
364 }
365
3660 this.checkBuffer(start + length);
367
3680 var offsetLeft
369 , offsetRight = start % 8
370 , curByte = this.buffer.length - ( start >> 3 ) - 1
371 , lastByte = this.buffer.length + ( -( start + length ) >> 3 )
372 , diff = curByte - lastByte
373 , sum = ((this.buffer[ curByte ] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1)) + (diff && (offsetLeft = (start + length) % 8) ? (this.buffer[lastByte++] & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight : 0);
374
3750 for(; diff; sum += shl(this.buffer[lastByte++], (diff-- << 3) - offsetRight));
376
3770 return sum;
378};
379
380/**
381 * Expose.
382 */
3831BinaryParser.Buffer = BinaryParserBuffer;
384
3851exports.BinaryParser = BinaryParser;
386

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/bson.js

10%
670
71
599
LineHitsSource
11var Long = require('./long').Long
2 , Double = require('./double').Double
3 , Timestamp = require('./timestamp').Timestamp
4 , ObjectID = require('./objectid').ObjectID
5 , Symbol = require('./symbol').Symbol
6 , Code = require('./code').Code
7 , MinKey = require('./min_key').MinKey
8 , MaxKey = require('./max_key').MaxKey
9 , DBRef = require('./db_ref').DBRef
10 , Binary = require('./binary').Binary
11 , BinaryParser = require('./binary_parser').BinaryParser
12 , writeIEEE754 = require('./float_parser').writeIEEE754
13 , readIEEE754 = require('./float_parser').readIEEE754
14
15// To ensure that 0.4 of node works correctly
161var isDate = function isDate(d) {
170 return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]';
18}
19
20/**
21 * Create a new BSON instance
22 *
23 * @class Represents the BSON Parser
24 * @return {BSON} instance of BSON Parser.
25 */
261function BSON () {};
27
28/**
29 * @ignore
30 * @api private
31 */
32// BSON MAX VALUES
331BSON.BSON_INT32_MAX = 0x7FFFFFFF;
341BSON.BSON_INT32_MIN = -0x80000000;
35
361BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1;
371BSON.BSON_INT64_MIN = -Math.pow(2, 63);
38
39// JS MAX PRECISE VALUES
401BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double.
411BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double.
42
43// Internal long versions
441var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double.
451var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double.
46
47/**
48 * Number BSON Type
49 *
50 * @classconstant BSON_DATA_NUMBER
51 **/
521BSON.BSON_DATA_NUMBER = 1;
53/**
54 * String BSON Type
55 *
56 * @classconstant BSON_DATA_STRING
57 **/
581BSON.BSON_DATA_STRING = 2;
59/**
60 * Object BSON Type
61 *
62 * @classconstant BSON_DATA_OBJECT
63 **/
641BSON.BSON_DATA_OBJECT = 3;
65/**
66 * Array BSON Type
67 *
68 * @classconstant BSON_DATA_ARRAY
69 **/
701BSON.BSON_DATA_ARRAY = 4;
71/**
72 * Binary BSON Type
73 *
74 * @classconstant BSON_DATA_BINARY
75 **/
761BSON.BSON_DATA_BINARY = 5;
77/**
78 * ObjectID BSON Type
79 *
80 * @classconstant BSON_DATA_OID
81 **/
821BSON.BSON_DATA_OID = 7;
83/**
84 * Boolean BSON Type
85 *
86 * @classconstant BSON_DATA_BOOLEAN
87 **/
881BSON.BSON_DATA_BOOLEAN = 8;
89/**
90 * Date BSON Type
91 *
92 * @classconstant BSON_DATA_DATE
93 **/
941BSON.BSON_DATA_DATE = 9;
95/**
96 * null BSON Type
97 *
98 * @classconstant BSON_DATA_NULL
99 **/
1001BSON.BSON_DATA_NULL = 10;
101/**
102 * RegExp BSON Type
103 *
104 * @classconstant BSON_DATA_REGEXP
105 **/
1061BSON.BSON_DATA_REGEXP = 11;
107/**
108 * Code BSON Type
109 *
110 * @classconstant BSON_DATA_CODE
111 **/
1121BSON.BSON_DATA_CODE = 13;
113/**
114 * Symbol BSON Type
115 *
116 * @classconstant BSON_DATA_SYMBOL
117 **/
1181BSON.BSON_DATA_SYMBOL = 14;
119/**
120 * Code with Scope BSON Type
121 *
122 * @classconstant BSON_DATA_CODE_W_SCOPE
123 **/
1241BSON.BSON_DATA_CODE_W_SCOPE = 15;
125/**
126 * 32 bit Integer BSON Type
127 *
128 * @classconstant BSON_DATA_INT
129 **/
1301BSON.BSON_DATA_INT = 16;
131/**
132 * Timestamp BSON Type
133 *
134 * @classconstant BSON_DATA_TIMESTAMP
135 **/
1361BSON.BSON_DATA_TIMESTAMP = 17;
137/**
138 * Long BSON Type
139 *
140 * @classconstant BSON_DATA_LONG
141 **/
1421BSON.BSON_DATA_LONG = 18;
143/**
144 * MinKey BSON Type
145 *
146 * @classconstant BSON_DATA_MIN_KEY
147 **/
1481BSON.BSON_DATA_MIN_KEY = 0xff;
149/**
150 * MaxKey BSON Type
151 *
152 * @classconstant BSON_DATA_MAX_KEY
153 **/
1541BSON.BSON_DATA_MAX_KEY = 0x7f;
155
156/**
157 * Binary Default Type
158 *
159 * @classconstant BSON_BINARY_SUBTYPE_DEFAULT
160 **/
1611BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0;
162/**
163 * Binary Function Type
164 *
165 * @classconstant BSON_BINARY_SUBTYPE_FUNCTION
166 **/
1671BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1;
168/**
169 * Binary Byte Array Type
170 *
171 * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY
172 **/
1731BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2;
174/**
175 * Binary UUID Type
176 *
177 * @classconstant BSON_BINARY_SUBTYPE_UUID
178 **/
1791BSON.BSON_BINARY_SUBTYPE_UUID = 3;
180/**
181 * Binary MD5 Type
182 *
183 * @classconstant BSON_BINARY_SUBTYPE_MD5
184 **/
1851BSON.BSON_BINARY_SUBTYPE_MD5 = 4;
186/**
187 * Binary User Defined Type
188 *
189 * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED
190 **/
1911BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128;
192
193/**
194 * Calculate the bson size for a passed in Javascript object.
195 *
196 * @param {Object} object the Javascript object to calculate the BSON byte size for.
197 * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**.
198 * @return {Number} returns the number of bytes the BSON object will take up.
199 * @api public
200 */
2011BSON.calculateObjectSize = function calculateObjectSize(object, serializeFunctions) {
2020 var totalLength = (4 + 1);
203
2040 if(Array.isArray(object)) {
2050 for(var i = 0; i < object.length; i++) {
2060 totalLength += calculateElement(i.toString(), object[i], serializeFunctions)
207 }
208 } else {
209 // If we have toBSON defined, override the current object
2100 if(object.toBSON) {
2110 object = object.toBSON();
212 }
213
214 // Calculate size
2150 for(var key in object) {
2160 totalLength += calculateElement(key, object[key], serializeFunctions)
217 }
218 }
219
2200 return totalLength;
221}
222
223/**
224 * @ignore
225 * @api private
226 */
2271function calculateElement(name, value, serializeFunctions) {
2280 var isBuffer = typeof Buffer !== 'undefined';
229
2300 switch(typeof value) {
231 case 'string':
2320 return 1 + (!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1 + 4 + (!isBuffer ? numberOfBytes(value) : Buffer.byteLength(value, 'utf8')) + 1;
233 case 'number':
2340 if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
2350 if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit
2360 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (4 + 1);
237 } else {
2380 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1);
239 }
240 } else { // 64 bit
2410 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1);
242 }
243 case 'undefined':
2440 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1);
245 case 'boolean':
2460 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 1);
247 case 'object':
2480 if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') {
2490 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1);
2500 } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') {
2510 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (12 + 1);
2520 } else if(value instanceof Date || isDate(value)) {
2530 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1);
2540 } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
2550 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 4 + 1) + value.length;
2560 } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp
257 || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') {
2580 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1);
2590 } else if(value instanceof Code || value['_bsontype'] == 'Code') {
260 // Calculate size depending on the availability of a scope
2610 if(value.scope != null && Object.keys(value.scope).length > 0) {
2620 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions);
263 } else {
2640 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1;
265 }
2660 } else if(value instanceof Binary || value['_bsontype'] == 'Binary') {
267 // Check what kind of subtype we have
2680 if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) {
2690 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1 + 4);
270 } else {
2710 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1);
272 }
2730 } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') {
2740 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + ((!isBuffer ? numberOfBytes(value.value) : Buffer.byteLength(value.value, 'utf8')) + 4 + 1 + 1);
2750 } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') {
276 // Set up correct object for serialization
2770 var ordered_values = {
278 '$ref': value.namespace
279 , '$id' : value.oid
280 };
281
282 // Add db reference if it exists
2830 if(null != value.db) {
2840 ordered_values['$db'] = value.db;
285 }
286
2870 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + BSON.calculateObjectSize(ordered_values, serializeFunctions);
2880 } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') {
2890 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1
290 + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1
291 } else {
2920 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + BSON.calculateObjectSize(value, serializeFunctions) + 1;
293 }
294 case 'function':
295 // WTF for 0.4.X where typeof /someregexp/ === 'function'
2960 if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') {
2970 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1
298 + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1
299 } else {
3000 if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) {
3010 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions);
3020 } else if(serializeFunctions) {
3030 return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1;
304 }
305 }
306 }
307
3080 return 0;
309}
310
311/**
312 * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization.
313 *
314 * @param {Object} object the Javascript object to serialize.
315 * @param {Boolean} checkKeys the serializer will check if keys are valid.
316 * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object.
317 * @param {Number} index the index in the buffer where we wish to start serializing into.
318 * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**.
319 * @return {Number} returns the new write index in the Buffer.
320 * @api public
321 */
3221BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, checkKeys, buffer, index, serializeFunctions) {
323 // Default setting false
3240 serializeFunctions = serializeFunctions == null ? false : serializeFunctions;
325 // Write end information (length of the object)
3260 var size = buffer.length;
327 // Write the size of the object
3280 buffer[index++] = size & 0xff;
3290 buffer[index++] = (size >> 8) & 0xff;
3300 buffer[index++] = (size >> 16) & 0xff;
3310 buffer[index++] = (size >> 24) & 0xff;
3320 return serializeObject(object, checkKeys, buffer, index, serializeFunctions) - 1;
333}
334
335/**
336 * @ignore
337 * @api private
338 */
3391var serializeObject = function(object, checkKeys, buffer, index, serializeFunctions) {
340 // Process the object
3410 if(Array.isArray(object)) {
3420 for(var i = 0; i < object.length; i++) {
3430 index = packElement(i.toString(), object[i], checkKeys, buffer, index, serializeFunctions);
344 }
345 } else {
346 // If we have toBSON defined, override the current object
3470 if(object.toBSON) {
3480 object = object.toBSON();
349 }
350
351 // Serialize the object
3520 for(var key in object) {
353 // Check the key and throw error if it's illegal
3540 if (key != '$db' && key != '$ref' && key != '$id') {
355 // dollars and dots ok
3560 BSON.checkKey(key, !checkKeys);
357 }
358
359 // Pack the element
3600 index = packElement(key, object[key], checkKeys, buffer, index, serializeFunctions);
361 }
362 }
363
364 // Write zero
3650 buffer[index++] = 0;
3660 return index;
367}
368
3691var stringToBytes = function(str) {
3700 var ch, st, re = [];
3710 for (var i = 0; i < str.length; i++ ) {
3720 ch = str.charCodeAt(i); // get char
3730 st = []; // set up "stack"
3740 do {
3750 st.push( ch & 0xFF ); // push byte to stack
3760 ch = ch >> 8; // shift value down by 1 byte
377 }
378 while ( ch );
379 // add stack contents to result
380 // done because chars have "wrong" endianness
3810 re = re.concat( st.reverse() );
382 }
383 // return an array of bytes
3840 return re;
385}
386
3871var numberOfBytes = function(str) {
3880 var ch, st, re = 0;
3890 for (var i = 0; i < str.length; i++ ) {
3900 ch = str.charCodeAt(i); // get char
3910 st = []; // set up "stack"
3920 do {
3930 st.push( ch & 0xFF ); // push byte to stack
3940 ch = ch >> 8; // shift value down by 1 byte
395 }
396 while ( ch );
397 // add stack contents to result
398 // done because chars have "wrong" endianness
3990 re = re + st.length;
400 }
401 // return an array of bytes
4020 return re;
403}
404
405/**
406 * @ignore
407 * @api private
408 */
4091var writeToTypedArray = function(buffer, string, index) {
4100 var bytes = stringToBytes(string);
4110 for(var i = 0; i < bytes.length; i++) {
4120 buffer[index + i] = bytes[i];
413 }
4140 return bytes.length;
415}
416
417/**
418 * @ignore
419 * @api private
420 */
4211var supportsBuffer = typeof Buffer != 'undefined';
422
423/**
424 * @ignore
425 * @api private
426 */
4271var packElement = function(name, value, checkKeys, buffer, index, serializeFunctions) {
4280 var startIndex = index;
429
4300 switch(typeof value) {
431 case 'string':
432 // Encode String type
4330 buffer[index++] = BSON.BSON_DATA_STRING;
434 // Number of written bytes
4350 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
436 // Encode the name
4370 index = index + numberOfWrittenBytes + 1;
4380 buffer[index - 1] = 0;
439
440 // Calculate size
4410 var size = supportsBuffer ? Buffer.byteLength(value) + 1 : numberOfBytes(value) + 1;
442 // Write the size of the string to buffer
4430 buffer[index + 3] = (size >> 24) & 0xff;
4440 buffer[index + 2] = (size >> 16) & 0xff;
4450 buffer[index + 1] = (size >> 8) & 0xff;
4460 buffer[index] = size & 0xff;
447 // Ajust the index
4480 index = index + 4;
449 // Write the string
4500 supportsBuffer ? buffer.write(value, index, 'utf8') : writeToTypedArray(buffer, value, index);
451 // Update index
4520 index = index + size - 1;
453 // Write zero
4540 buffer[index++] = 0;
455 // Return index
4560 return index;
457 case 'number':
458 // We have an integer value
4590 if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
460 // If the value fits in 32 bits encode as int, if it fits in a double
461 // encode it as a double, otherwise long
4620 if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) {
463 // Set int type 32 bits or less
4640 buffer[index++] = BSON.BSON_DATA_INT;
465 // Number of written bytes
4660 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
467 // Encode the name
4680 index = index + numberOfWrittenBytes + 1;
4690 buffer[index - 1] = 0;
470 // Write the int value
4710 buffer[index++] = value & 0xff;
4720 buffer[index++] = (value >> 8) & 0xff;
4730 buffer[index++] = (value >> 16) & 0xff;
4740 buffer[index++] = (value >> 24) & 0xff;
4750 } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
476 // Encode as double
4770 buffer[index++] = BSON.BSON_DATA_NUMBER;
478 // Number of written bytes
4790 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
480 // Encode the name
4810 index = index + numberOfWrittenBytes + 1;
4820 buffer[index - 1] = 0;
483 // Write float
4840 writeIEEE754(buffer, value, index, 'little', 52, 8);
485 // Ajust index
4860 index = index + 8;
487 } else {
488 // Set long type
4890 buffer[index++] = BSON.BSON_DATA_LONG;
490 // Number of written bytes
4910 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
492 // Encode the name
4930 index = index + numberOfWrittenBytes + 1;
4940 buffer[index - 1] = 0;
4950 var longVal = Long.fromNumber(value);
4960 var lowBits = longVal.getLowBits();
4970 var highBits = longVal.getHighBits();
498 // Encode low bits
4990 buffer[index++] = lowBits & 0xff;
5000 buffer[index++] = (lowBits >> 8) & 0xff;
5010 buffer[index++] = (lowBits >> 16) & 0xff;
5020 buffer[index++] = (lowBits >> 24) & 0xff;
503 // Encode high bits
5040 buffer[index++] = highBits & 0xff;
5050 buffer[index++] = (highBits >> 8) & 0xff;
5060 buffer[index++] = (highBits >> 16) & 0xff;
5070 buffer[index++] = (highBits >> 24) & 0xff;
508 }
509 } else {
510 // Encode as double
5110 buffer[index++] = BSON.BSON_DATA_NUMBER;
512 // Number of written bytes
5130 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
514 // Encode the name
5150 index = index + numberOfWrittenBytes + 1;
5160 buffer[index - 1] = 0;
517 // Write float
5180 writeIEEE754(buffer, value, index, 'little', 52, 8);
519 // Ajust index
5200 index = index + 8;
521 }
522
5230 return index;
524 case 'undefined':
525 // Set long type
5260 buffer[index++] = BSON.BSON_DATA_NULL;
527 // Number of written bytes
5280 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
529 // Encode the name
5300 index = index + numberOfWrittenBytes + 1;
5310 buffer[index - 1] = 0;
5320 return index;
533 case 'boolean':
534 // Write the type
5350 buffer[index++] = BSON.BSON_DATA_BOOLEAN;
536 // Number of written bytes
5370 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
538 // Encode the name
5390 index = index + numberOfWrittenBytes + 1;
5400 buffer[index - 1] = 0;
541 // Encode the boolean value
5420 buffer[index++] = value ? 1 : 0;
5430 return index;
544 case 'object':
5450 if(value === null || value instanceof MinKey || value instanceof MaxKey
546 || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') {
547 // Write the type of either min or max key
5480 if(value === null) {
5490 buffer[index++] = BSON.BSON_DATA_NULL;
5500 } else if(value instanceof MinKey) {
5510 buffer[index++] = BSON.BSON_DATA_MIN_KEY;
552 } else {
5530 buffer[index++] = BSON.BSON_DATA_MAX_KEY;
554 }
555
556 // Number of written bytes
5570 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
558 // Encode the name
5590 index = index + numberOfWrittenBytes + 1;
5600 buffer[index - 1] = 0;
5610 return index;
5620 } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') {
563 // Write the type
5640 buffer[index++] = BSON.BSON_DATA_OID;
565 // Number of written bytes
5660 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
567 // Encode the name
5680 index = index + numberOfWrittenBytes + 1;
5690 buffer[index - 1] = 0;
570
571 // Write objectid
5720 supportsBuffer ? buffer.write(value.id, index, 'binary') : writeToTypedArray(buffer, value.id, index);
573 // Ajust index
5740 index = index + 12;
5750 return index;
5760 } else if(value instanceof Date || isDate(value)) {
577 // Write the type
5780 buffer[index++] = BSON.BSON_DATA_DATE;
579 // Number of written bytes
5800 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
581 // Encode the name
5820 index = index + numberOfWrittenBytes + 1;
5830 buffer[index - 1] = 0;
584
585 // Write the date
5860 var dateInMilis = Long.fromNumber(value.getTime());
5870 var lowBits = dateInMilis.getLowBits();
5880 var highBits = dateInMilis.getHighBits();
589 // Encode low bits
5900 buffer[index++] = lowBits & 0xff;
5910 buffer[index++] = (lowBits >> 8) & 0xff;
5920 buffer[index++] = (lowBits >> 16) & 0xff;
5930 buffer[index++] = (lowBits >> 24) & 0xff;
594 // Encode high bits
5950 buffer[index++] = highBits & 0xff;
5960 buffer[index++] = (highBits >> 8) & 0xff;
5970 buffer[index++] = (highBits >> 16) & 0xff;
5980 buffer[index++] = (highBits >> 24) & 0xff;
5990 return index;
6000 } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
601 // Write the type
6020 buffer[index++] = BSON.BSON_DATA_BINARY;
603 // Number of written bytes
6040 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
605 // Encode the name
6060 index = index + numberOfWrittenBytes + 1;
6070 buffer[index - 1] = 0;
608 // Get size of the buffer (current write point)
6090 var size = value.length;
610 // Write the size of the string to buffer
6110 buffer[index++] = size & 0xff;
6120 buffer[index++] = (size >> 8) & 0xff;
6130 buffer[index++] = (size >> 16) & 0xff;
6140 buffer[index++] = (size >> 24) & 0xff;
615 // Write the default subtype
6160 buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT;
617 // Copy the content form the binary field to the buffer
6180 value.copy(buffer, index, 0, size);
619 // Adjust the index
6200 index = index + size;
6210 return index;
6220 } else if(value instanceof Long || value instanceof Timestamp || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Timestamp') {
623 // Write the type
6240 buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP;
625 // Number of written bytes
6260 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
627 // Encode the name
6280 index = index + numberOfWrittenBytes + 1;
6290 buffer[index - 1] = 0;
630 // Write the date
6310 var lowBits = value.getLowBits();
6320 var highBits = value.getHighBits();
633 // Encode low bits
6340 buffer[index++] = lowBits & 0xff;
6350 buffer[index++] = (lowBits >> 8) & 0xff;
6360 buffer[index++] = (lowBits >> 16) & 0xff;
6370 buffer[index++] = (lowBits >> 24) & 0xff;
638 // Encode high bits
6390 buffer[index++] = highBits & 0xff;
6400 buffer[index++] = (highBits >> 8) & 0xff;
6410 buffer[index++] = (highBits >> 16) & 0xff;
6420 buffer[index++] = (highBits >> 24) & 0xff;
6430 return index;
6440 } else if(value instanceof Double || value['_bsontype'] == 'Double') {
645 // Encode as double
6460 buffer[index++] = BSON.BSON_DATA_NUMBER;
647 // Number of written bytes
6480 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
649 // Encode the name
6500 index = index + numberOfWrittenBytes + 1;
6510 buffer[index - 1] = 0;
652 // Write float
6530 writeIEEE754(buffer, value, index, 'little', 52, 8);
654 // Ajust index
6550 index = index + 8;
6560 return index;
6570 } else if(value instanceof Code || value['_bsontype'] == 'Code') {
6580 if(value.scope != null && Object.keys(value.scope).length > 0) {
659 // Write the type
6600 buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE;
661 // Number of written bytes
6620 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
663 // Encode the name
6640 index = index + numberOfWrittenBytes + 1;
6650 buffer[index - 1] = 0;
666 // Calculate the scope size
6670 var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions);
668 // Function string
6690 var functionString = value.code.toString();
670 // Function Size
6710 var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1;
672
673 // Calculate full size of the object
6740 var totalSize = 4 + codeSize + scopeSize + 4;
675
676 // Write the total size of the object
6770 buffer[index++] = totalSize & 0xff;
6780 buffer[index++] = (totalSize >> 8) & 0xff;
6790 buffer[index++] = (totalSize >> 16) & 0xff;
6800 buffer[index++] = (totalSize >> 24) & 0xff;
681
682 // Write the size of the string to buffer
6830 buffer[index++] = codeSize & 0xff;
6840 buffer[index++] = (codeSize >> 8) & 0xff;
6850 buffer[index++] = (codeSize >> 16) & 0xff;
6860 buffer[index++] = (codeSize >> 24) & 0xff;
687
688 // Write the string
6890 supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index);
690 // Update index
6910 index = index + codeSize - 1;
692 // Write zero
6930 buffer[index++] = 0;
694 // Serialize the scope object
6950 var scopeObjectBuffer = supportsBuffer ? new Buffer(scopeSize) : new Uint8Array(new ArrayBuffer(scopeSize));
696 // Execute the serialization into a seperate buffer
6970 serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions);
698
699 // Adjusted scope Size (removing the header)
7000 var scopeDocSize = scopeSize;
701 // Write scope object size
7020 buffer[index++] = scopeDocSize & 0xff;
7030 buffer[index++] = (scopeDocSize >> 8) & 0xff;
7040 buffer[index++] = (scopeDocSize >> 16) & 0xff;
7050 buffer[index++] = (scopeDocSize >> 24) & 0xff;
706
707 // Write the scopeObject into the buffer
7080 supportsBuffer ? scopeObjectBuffer.copy(buffer, index, 0, scopeSize) : buffer.set(scopeObjectBuffer, index);
709 // Adjust index, removing the empty size of the doc (5 bytes 0000000005)
7100 index = index + scopeDocSize - 5;
711 // Write trailing zero
7120 buffer[index++] = 0;
7130 return index
714 } else {
7150 buffer[index++] = BSON.BSON_DATA_CODE;
716 // Number of written bytes
7170 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
718 // Encode the name
7190 index = index + numberOfWrittenBytes + 1;
7200 buffer[index - 1] = 0;
721 // Function string
7220 var functionString = value.code.toString();
723 // Function Size
7240 var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1;
725 // Write the size of the string to buffer
7260 buffer[index++] = size & 0xff;
7270 buffer[index++] = (size >> 8) & 0xff;
7280 buffer[index++] = (size >> 16) & 0xff;
7290 buffer[index++] = (size >> 24) & 0xff;
730 // Write the string
7310 supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index);
732 // Update index
7330 index = index + size - 1;
734 // Write zero
7350 buffer[index++] = 0;
7360 return index;
737 }
7380 } else if(value instanceof Binary || value['_bsontype'] == 'Binary') {
739 // Write the type
7400 buffer[index++] = BSON.BSON_DATA_BINARY;
741 // Number of written bytes
7420 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
743 // Encode the name
7440 index = index + numberOfWrittenBytes + 1;
7450 buffer[index - 1] = 0;
746 // Extract the buffer
7470 var data = value.value(true);
748 // Calculate size
7490 var size = value.position;
750 // Write the size of the string to buffer
7510 buffer[index++] = size & 0xff;
7520 buffer[index++] = (size >> 8) & 0xff;
7530 buffer[index++] = (size >> 16) & 0xff;
7540 buffer[index++] = (size >> 24) & 0xff;
755 // Write the subtype to the buffer
7560 buffer[index++] = value.sub_type;
757
758 // If we have binary type 2 the 4 first bytes are the size
7590 if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) {
7600 buffer[index++] = size & 0xff;
7610 buffer[index++] = (size >> 8) & 0xff;
7620 buffer[index++] = (size >> 16) & 0xff;
7630 buffer[index++] = (size >> 24) & 0xff;
764 }
765
766 // Write the data to the object
7670 supportsBuffer ? data.copy(buffer, index, 0, value.position) : buffer.set(data, index);
768 // Ajust index
7690 index = index + value.position;
7700 return index;
7710 } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') {
772 // Write the type
7730 buffer[index++] = BSON.BSON_DATA_SYMBOL;
774 // Number of written bytes
7750 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
776 // Encode the name
7770 index = index + numberOfWrittenBytes + 1;
7780 buffer[index - 1] = 0;
779 // Calculate size
7800 var size = supportsBuffer ? Buffer.byteLength(value.value) + 1 : numberOfBytes(value.value) + 1;
781 // Write the size of the string to buffer
7820 buffer[index++] = size & 0xff;
7830 buffer[index++] = (size >> 8) & 0xff;
7840 buffer[index++] = (size >> 16) & 0xff;
7850 buffer[index++] = (size >> 24) & 0xff;
786 // Write the string
7870 buffer.write(value.value, index, 'utf8');
788 // Update index
7890 index = index + size - 1;
790 // Write zero
7910 buffer[index++] = 0x00;
7920 return index;
7930 } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') {
794 // Write the type
7950 buffer[index++] = BSON.BSON_DATA_OBJECT;
796 // Number of written bytes
7970 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
798 // Encode the name
7990 index = index + numberOfWrittenBytes + 1;
8000 buffer[index - 1] = 0;
801 // Set up correct object for serialization
8020 var ordered_values = {
803 '$ref': value.namespace
804 , '$id' : value.oid
805 };
806
807 // Add db reference if it exists
8080 if(null != value.db) {
8090 ordered_values['$db'] = value.db;
810 }
811
812 // Message size
8130 var size = BSON.calculateObjectSize(ordered_values, serializeFunctions);
814 // Serialize the object
8150 var endIndex = BSON.serializeWithBufferAndIndex(ordered_values, checkKeys, buffer, index, serializeFunctions);
816 // Write the size of the string to buffer
8170 buffer[index++] = size & 0xff;
8180 buffer[index++] = (size >> 8) & 0xff;
8190 buffer[index++] = (size >> 16) & 0xff;
8200 buffer[index++] = (size >> 24) & 0xff;
821 // Write zero for object
8220 buffer[endIndex++] = 0x00;
823 // Return the end index
8240 return endIndex;
8250 } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') {
826 // Write the type
8270 buffer[index++] = BSON.BSON_DATA_REGEXP;
828 // Number of written bytes
8290 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
830 // Encode the name
8310 index = index + numberOfWrittenBytes + 1;
8320 buffer[index - 1] = 0;
833
834 // Write the regular expression string
8350 supportsBuffer ? buffer.write(value.source, index, 'utf8') : writeToTypedArray(buffer, value.source, index);
836 // Adjust the index
8370 index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source));
838 // Write zero
8390 buffer[index++] = 0x00;
840 // Write the parameters
8410 if(value.global) buffer[index++] = 0x73; // s
8420 if(value.ignoreCase) buffer[index++] = 0x69; // i
8430 if(value.multiline) buffer[index++] = 0x6d; // m
844 // Add ending zero
8450 buffer[index++] = 0x00;
8460 return index;
847 } else {
848 // Write the type
8490 buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT;
850 // Number of written bytes
8510 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
852 // Adjust the index
8530 index = index + numberOfWrittenBytes + 1;
8540 buffer[index - 1] = 0;
8550 var endIndex = serializeObject(value, checkKeys, buffer, index + 4, serializeFunctions);
856 // Write size
8570 var size = endIndex - index;
858 // Write the size of the string to buffer
8590 buffer[index++] = size & 0xff;
8600 buffer[index++] = (size >> 8) & 0xff;
8610 buffer[index++] = (size >> 16) & 0xff;
8620 buffer[index++] = (size >> 24) & 0xff;
8630 return endIndex;
864 }
865 case 'function':
866 // WTF for 0.4.X where typeof /someregexp/ === 'function'
8670 if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') {
868 // Write the type
8690 buffer[index++] = BSON.BSON_DATA_REGEXP;
870 // Number of written bytes
8710 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
872 // Encode the name
8730 index = index + numberOfWrittenBytes + 1;
8740 buffer[index - 1] = 0;
875
876 // Write the regular expression string
8770 buffer.write(value.source, index, 'utf8');
878 // Adjust the index
8790 index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source));
880 // Write zero
8810 buffer[index++] = 0x00;
882 // Write the parameters
8830 if(value.global) buffer[index++] = 0x73; // s
8840 if(value.ignoreCase) buffer[index++] = 0x69; // i
8850 if(value.multiline) buffer[index++] = 0x6d; // m
886 // Add ending zero
8870 buffer[index++] = 0x00;
8880 return index;
889 } else {
8900 if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) {
891 // Write the type
8920 buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE;
893 // Number of written bytes
8940 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
895 // Encode the name
8960 index = index + numberOfWrittenBytes + 1;
8970 buffer[index - 1] = 0;
898 // Calculate the scope size
8990 var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions);
900 // Function string
9010 var functionString = value.toString();
902 // Function Size
9030 var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1;
904
905 // Calculate full size of the object
9060 var totalSize = 4 + codeSize + scopeSize;
907
908 // Write the total size of the object
9090 buffer[index++] = totalSize & 0xff;
9100 buffer[index++] = (totalSize >> 8) & 0xff;
9110 buffer[index++] = (totalSize >> 16) & 0xff;
9120 buffer[index++] = (totalSize >> 24) & 0xff;
913
914 // Write the size of the string to buffer
9150 buffer[index++] = codeSize & 0xff;
9160 buffer[index++] = (codeSize >> 8) & 0xff;
9170 buffer[index++] = (codeSize >> 16) & 0xff;
9180 buffer[index++] = (codeSize >> 24) & 0xff;
919
920 // Write the string
9210 supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index);
922 // Update index
9230 index = index + codeSize - 1;
924 // Write zero
9250 buffer[index++] = 0;
926 // Serialize the scope object
9270 var scopeObjectBuffer = new Buffer(scopeSize);
928 // Execute the serialization into a seperate buffer
9290 serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions);
930
931 // Adjusted scope Size (removing the header)
9320 var scopeDocSize = scopeSize - 4;
933 // Write scope object size
9340 buffer[index++] = scopeDocSize & 0xff;
9350 buffer[index++] = (scopeDocSize >> 8) & 0xff;
9360 buffer[index++] = (scopeDocSize >> 16) & 0xff;
9370 buffer[index++] = (scopeDocSize >> 24) & 0xff;
938
939 // Write the scopeObject into the buffer
9400 scopeObjectBuffer.copy(buffer, index, 0, scopeSize);
941
942 // Adjust index, removing the empty size of the doc (5 bytes 0000000005)
9430 index = index + scopeDocSize - 5;
944 // Write trailing zero
9450 buffer[index++] = 0;
9460 return index
9470 } else if(serializeFunctions) {
9480 buffer[index++] = BSON.BSON_DATA_CODE;
949 // Number of written bytes
9500 var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index);
951 // Encode the name
9520 index = index + numberOfWrittenBytes + 1;
9530 buffer[index - 1] = 0;
954 // Function string
9550 var functionString = value.toString();
956 // Function Size
9570 var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1;
958 // Write the size of the string to buffer
9590 buffer[index++] = size & 0xff;
9600 buffer[index++] = (size >> 8) & 0xff;
9610 buffer[index++] = (size >> 16) & 0xff;
9620 buffer[index++] = (size >> 24) & 0xff;
963 // Write the string
9640 supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index);
965 // Update index
9660 index = index + size - 1;
967 // Write zero
9680 buffer[index++] = 0;
9690 return index;
970 }
971 }
972 }
973
974 // If no value to serialize
9750 return index;
976}
977
978/**
979 * Serialize a Javascript object.
980 *
981 * @param {Object} object the Javascript object to serialize.
982 * @param {Boolean} checkKeys the serializer will check if keys are valid.
983 * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**.
984 * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**.
985 * @return {Buffer} returns the Buffer object containing the serialized object.
986 * @api public
987 */
9881BSON.serialize = function(object, checkKeys, asBuffer, serializeFunctions) {
989 // Throw error if we are trying serialize an illegal type
9900 if(object == null || typeof object != 'object' || Array.isArray(object))
9910 throw new Error("Only javascript objects supported");
992
993 // Emoty target buffer
9940 var buffer = null;
995 // Calculate the size of the object
9960 var size = BSON.calculateObjectSize(object, serializeFunctions);
997 // Fetch the best available type for storing the binary data
9980 if(buffer = typeof Buffer != 'undefined') {
9990 buffer = new Buffer(size);
10000 asBuffer = true;
10010 } else if(typeof Uint8Array != 'undefined') {
10020 buffer = new Uint8Array(new ArrayBuffer(size));
1003 } else {
10040 buffer = new Array(size);
1005 }
1006
1007 // If asBuffer is false use typed arrays
10080 BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, 0, serializeFunctions);
10090 return buffer;
1010}
1011
1012/**
1013 * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5
1014 *
1015 * @ignore
1016 * @api private
1017 */
10181var functionCache = BSON.functionCache = {};
1019
1020/**
1021 * Crc state variables shared by function
1022 *
1023 * @ignore
1024 * @api private
1025 */
10261var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D];
1027
1028/**
1029 * CRC32 hash method, Fast and enough versitility for our usage
1030 *
1031 * @ignore
1032 * @api private
1033 */
10341var crc32 = function(string, start, end) {
10350 var crc = 0
10360 var x = 0;
10370 var y = 0;
10380 crc = crc ^ (-1);
1039
10400 for(var i = start, iTop = end; i < iTop;i++) {
10410 y = (crc ^ string[i]) & 0xFF;
10420 x = table[y];
10430 crc = (crc >>> 8) ^ x;
1044 }
1045
10460 return crc ^ (-1);
1047}
1048
1049/**
1050 * Deserialize stream data as BSON documents.
1051 *
1052 * Options
1053 * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized.
1054 * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse.
1055 * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function.
1056 * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits
1057 *
1058 * @param {Buffer} data the buffer containing the serialized set of BSON documents.
1059 * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start.
1060 * @param {Number} numberOfDocuments number of documents to deserialize.
1061 * @param {Array} documents an array where to store the deserialized documents.
1062 * @param {Number} docStartIndex the index in the documents array from where to start inserting documents.
1063 * @param {Object} [options] additional options used for the deserialization.
1064 * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents.
1065 * @api public
1066 */
10671BSON.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) {
1068 // if(numberOfDocuments !== documents.length) throw new Error("Number of expected results back is less than the number of documents");
10690 options = options != null ? options : {};
10700 var index = startIndex;
1071 // Loop over all documents
10720 for(var i = 0; i < numberOfDocuments; i++) {
1073 // Find size of the document
10740 var size = data[index] | data[index + 1] << 8 | data[index + 2] << 16 | data[index + 3] << 24;
1075 // Update options with index
10760 options['index'] = index;
1077 // Parse the document at this point
10780 documents[docStartIndex + i] = BSON.deserialize(data, options);
1079 // Adjust index by the document size
10800 index = index + size;
1081 }
1082
1083 // Return object containing end index of parsing and list of documents
10840 return index;
1085}
1086
1087/**
1088 * Ensure eval is isolated.
1089 *
1090 * @ignore
1091 * @api private
1092 */
10931var isolateEvalWithHash = function(functionCache, hash, functionString, object) {
1094 // Contains the value we are going to set
10950 var value = null;
1096
1097 // Check for cache hit, eval if missing and return cached function
10980 if(functionCache[hash] == null) {
10990 eval("value = " + functionString);
11000 functionCache[hash] = value;
1101 }
1102 // Set the object
11030 return functionCache[hash].bind(object);
1104}
1105
1106/**
1107 * Ensure eval is isolated.
1108 *
1109 * @ignore
1110 * @api private
1111 */
11121var isolateEval = function(functionString) {
1113 // Contains the value we are going to set
11140 var value = null;
1115 // Eval the function
11160 eval("value = " + functionString);
11170 return value;
1118}
1119
1120/**
1121 * Convert Uint8Array to String
1122 *
1123 * @ignore
1124 * @api private
1125 */
11261var convertUint8ArrayToUtf8String = function(byteArray, startIndex, endIndex) {
11270 return BinaryParser.decode_utf8(convertArraytoUtf8BinaryString(byteArray, startIndex, endIndex));
1128}
1129
11301var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) {
11310 var result = "";
11320 for(var i = startIndex; i < endIndex; i++) {
11330 result = result + String.fromCharCode(byteArray[i]);
1134 }
1135
11360 return result;
1137};
1138
1139/**
1140 * Deserialize data as BSON.
1141 *
1142 * Options
1143 * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized.
1144 * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse.
1145 * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function.
1146 * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits
1147 *
1148 * @param {Buffer} buffer the buffer containing the serialized set of BSON documents.
1149 * @param {Object} [options] additional options used for the deserialization.
1150 * @param {Boolean} [isArray] ignore used for recursive parsing.
1151 * @return {Object} returns the deserialized Javascript Object.
1152 * @api public
1153 */
11541BSON.deserialize = function(buffer, options, isArray) {
1155 // Options
11560 options = options == null ? {} : options;
11570 var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
11580 var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions'];
11590 var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32'];
11600 var promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs'];
1161
1162 // Validate that we have at least 4 bytes of buffer
11630 if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long");
1164
1165 // Set up index
11660 var index = typeof options['index'] == 'number' ? options['index'] : 0;
1167 // Reads in a C style string
11680 var readCStyleString = function() {
1169 // Get the start search index
11700 var i = index;
1171 // Locate the end of the c string
11720 while(buffer[i] !== 0x00 && i < buffer.length) {
11730 i++
1174 }
1175 // If are at the end of the buffer there is a problem with the document
11760 if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
1177 // Grab utf8 encoded string
11780 var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, i) : convertUint8ArrayToUtf8String(buffer, index, i);
1179 // Update index position
11800 index = i + 1;
1181 // Return string
11820 return string;
1183 }
1184
1185 // Create holding object
11860 var object = isArray ? [] : {};
1187
1188 // Read the document size
11890 var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1190
1191 // Ensure buffer is valid size
11920 if(size < 5 || size > buffer.length) throw new Error("corrupt bson message");
1193
1194 // While we have more left data left keep parsing
11950 while(true) {
1196 // Read the type
11970 var elementType = buffer[index++];
1198 // If we get a zero it's the last byte, exit
11990 if(elementType == 0) break;
1200 // Read the name of the field
12010 var name = readCStyleString();
1202 // Switch on the type
12030 switch(elementType) {
1204 case BSON.BSON_DATA_OID:
12050 var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('binary', index, index + 12) : convertArraytoUtf8BinaryString(buffer, index, index + 12);
1206 // Decode the oid
12070 object[name] = new ObjectID(string);
1208 // Update index
12090 index = index + 12;
12100 break;
1211 case BSON.BSON_DATA_STRING:
1212 // Read the content of the field
12130 var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1214 // Add string to object
12150 object[name] = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1);
1216 // Update parse index position
12170 index = index + stringSize;
12180 break;
1219 case BSON.BSON_DATA_INT:
1220 // Decode the 32bit value
12210 object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
12220 break;
1223 case BSON.BSON_DATA_NUMBER:
1224 // Decode the double value
12250 object[name] = readIEEE754(buffer, index, 'little', 52, 8);
1226 // Update the index
12270 index = index + 8;
12280 break;
1229 case BSON.BSON_DATA_DATE:
1230 // Unpack the low and high bits
12310 var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
12320 var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1233 // Set date object
12340 object[name] = new Date(new Long(lowBits, highBits).toNumber());
12350 break;
1236 case BSON.BSON_DATA_BOOLEAN:
1237 // Parse the boolean value
12380 object[name] = buffer[index++] == 1;
12390 break;
1240 case BSON.BSON_DATA_NULL:
1241 // Parse the boolean value
12420 object[name] = null;
12430 break;
1244 case BSON.BSON_DATA_BINARY:
1245 // Decode the size of the binary blob
12460 var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1247 // Decode the subtype
12480 var subType = buffer[index++];
1249 // Decode as raw Buffer object if options specifies it
12500 if(buffer['slice'] != null) {
1251 // If we have subtype 2 skip the 4 bytes for the size
12520 if(subType == Binary.SUBTYPE_BYTE_ARRAY) {
12530 binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1254 }
1255 // Slice the data
12560 object[name] = new Binary(buffer.slice(index, index + binarySize), subType);
1257 } else {
12580 var _buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(binarySize)) : new Array(binarySize);
1259 // If we have subtype 2 skip the 4 bytes for the size
12600 if(subType == Binary.SUBTYPE_BYTE_ARRAY) {
12610 binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1262 }
1263 // Copy the data
12640 for(var i = 0; i < binarySize; i++) {
12650 _buffer[i] = buffer[index + i];
1266 }
1267 // Create the binary object
12680 object[name] = new Binary(_buffer, subType);
1269 }
1270 // Update the index
12710 index = index + binarySize;
12720 break;
1273 case BSON.BSON_DATA_ARRAY:
12740 options['index'] = index;
1275 // Decode the size of the array document
12760 var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
1277 // Set the array to the object
12780 object[name] = BSON.deserialize(buffer, options, true);
1279 // Adjust the index
12800 index = index + objectSize;
12810 break;
1282 case BSON.BSON_DATA_OBJECT:
12830 options['index'] = index;
1284 // Decode the size of the object document
12850 var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
1286 // Set the array to the object
12870 object[name] = BSON.deserialize(buffer, options, false);
1288 // Adjust the index
12890 index = index + objectSize;
12900 break;
1291 case BSON.BSON_DATA_REGEXP:
1292 // Create the regexp
12930 var source = readCStyleString();
12940 var regExpOptions = readCStyleString();
1295 // For each option add the corresponding one for javascript
12960 var optionsArray = new Array(regExpOptions.length);
1297
1298 // Parse options
12990 for(var i = 0; i < regExpOptions.length; i++) {
13000 switch(regExpOptions[i]) {
1301 case 'm':
13020 optionsArray[i] = 'm';
13030 break;
1304 case 's':
13050 optionsArray[i] = 'g';
13060 break;
1307 case 'i':
13080 optionsArray[i] = 'i';
13090 break;
1310 }
1311 }
1312
13130 object[name] = new RegExp(source, optionsArray.join(''));
13140 break;
1315 case BSON.BSON_DATA_LONG:
1316 // Unpack the low and high bits
13170 var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
13180 var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1319 // Create long object
13200 var long = new Long(lowBits, highBits);
1321 // Promote the long if possible
13220 if(promoteLongs) {
13230 object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long;
1324 } else {
13250 object[name] = long;
1326 }
13270 break;
1328 case BSON.BSON_DATA_SYMBOL:
1329 // Read the content of the field
13300 var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1331 // Add string to object
13320 object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1));
1333 // Update parse index position
13340 index = index + stringSize;
13350 break;
1336 case BSON.BSON_DATA_TIMESTAMP:
1337 // Unpack the low and high bits
13380 var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
13390 var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1340 // Set the object
13410 object[name] = new Timestamp(lowBits, highBits);
13420 break;
1343 case BSON.BSON_DATA_MIN_KEY:
1344 // Parse the object
13450 object[name] = new MinKey();
13460 break;
1347 case BSON.BSON_DATA_MAX_KEY:
1348 // Parse the object
13490 object[name] = new MaxKey();
13500 break;
1351 case BSON.BSON_DATA_CODE:
1352 // Read the content of the field
13530 var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1354 // Function string
13550 var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1);
1356
1357 // If we are evaluating the functions
13580 if(evalFunctions) {
1359 // Contains the value we are going to set
13600 var value = null;
1361 // If we have cache enabled let's look for the md5 of the function in the cache
13620 if(cacheFunctions) {
13630 var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString;
1364 // Got to do this to avoid V8 deoptimizing the call due to finding eval
13650 object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
1366 } else {
1367 // Set directly
13680 object[name] = isolateEval(functionString);
1369 }
1370 } else {
13710 object[name] = new Code(functionString, {});
1372 }
1373
1374 // Update parse index position
13750 index = index + stringSize;
13760 break;
1377 case BSON.BSON_DATA_CODE_W_SCOPE:
1378 // Read the content of the field
13790 var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
13800 var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
1381 // Javascript function
13820 var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1);
1383 // Update parse index position
13840 index = index + stringSize;
1385 // Parse the element
13860 options['index'] = index;
1387 // Decode the size of the object document
13880 var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
1389 // Decode the scope object
13900 var scopeObject = BSON.deserialize(buffer, options, false);
1391 // Adjust the index
13920 index = index + objectSize;
1393
1394 // If we are evaluating the functions
13950 if(evalFunctions) {
1396 // Contains the value we are going to set
13970 var value = null;
1398 // If we have cache enabled let's look for the md5 of the function in the cache
13990 if(cacheFunctions) {
14000 var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString;
1401 // Got to do this to avoid V8 deoptimizing the call due to finding eval
14020 object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
1403 } else {
1404 // Set directly
14050 object[name] = isolateEval(functionString);
1406 }
1407
1408 // Set the scope on the object
14090 object[name].scope = scopeObject;
1410 } else {
14110 object[name] = new Code(functionString, scopeObject);
1412 }
1413
1414 // Add string to object
14150 break;
1416 }
1417 }
1418
1419 // Check if we have a db ref object
14200 if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']);
1421
1422 // Return the final objects
14230 return object;
1424}
1425
1426/**
1427 * Check if key name is valid.
1428 *
1429 * @ignore
1430 * @api private
1431 */
14321BSON.checkKey = function checkKey (key, dollarsAndDotsOk) {
14330 if (!key.length) return;
1434 // Check if we have a legal key for the object
14350 if (!!~key.indexOf("\x00")) {
1436 // The BSON spec doesn't allow keys with null bytes because keys are
1437 // null-terminated.
14380 throw Error("key " + key + " must not contain null bytes");
1439 }
14400 if (!dollarsAndDotsOk) {
14410 if('$' == key[0]) {
14420 throw Error("key " + key + " must not start with '$'");
14430 } else if (!!~key.indexOf('.')) {
14440 throw Error("key " + key + " must not contain '.'");
1445 }
1446 }
1447};
1448
1449/**
1450 * Deserialize data as BSON.
1451 *
1452 * Options
1453 * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized.
1454 * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse.
1455 * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function.
1456 *
1457 * @param {Buffer} buffer the buffer containing the serialized set of BSON documents.
1458 * @param {Object} [options] additional options used for the deserialization.
1459 * @param {Boolean} [isArray] ignore used for recursive parsing.
1460 * @return {Object} returns the deserialized Javascript Object.
1461 * @api public
1462 */
14631BSON.prototype.deserialize = function(data, options) {
14640 return BSON.deserialize(data, options);
1465}
1466
1467/**
1468 * Deserialize stream data as BSON documents.
1469 *
1470 * Options
1471 * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized.
1472 * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse.
1473 * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function.
1474 *
1475 * @param {Buffer} data the buffer containing the serialized set of BSON documents.
1476 * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start.
1477 * @param {Number} numberOfDocuments number of documents to deserialize.
1478 * @param {Array} documents an array where to store the deserialized documents.
1479 * @param {Number} docStartIndex the index in the documents array from where to start inserting documents.
1480 * @param {Object} [options] additional options used for the deserialization.
1481 * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents.
1482 * @api public
1483 */
14841BSON.prototype.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) {
14850 return BSON.deserializeStream(data, startIndex, numberOfDocuments, documents, docStartIndex, options);
1486}
1487
1488/**
1489 * Serialize a Javascript object.
1490 *
1491 * @param {Object} object the Javascript object to serialize.
1492 * @param {Boolean} checkKeys the serializer will check if keys are valid.
1493 * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**.
1494 * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**.
1495 * @return {Buffer} returns the Buffer object containing the serialized object.
1496 * @api public
1497 */
14981BSON.prototype.serialize = function(object, checkKeys, asBuffer, serializeFunctions) {
14990 return BSON.serialize(object, checkKeys, asBuffer, serializeFunctions);
1500}
1501
1502/**
1503 * Calculate the bson size for a passed in Javascript object.
1504 *
1505 * @param {Object} object the Javascript object to calculate the BSON byte size for.
1506 * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**.
1507 * @return {Number} returns the number of bytes the BSON object will take up.
1508 * @api public
1509 */
15101BSON.prototype.calculateObjectSize = function(object, serializeFunctions) {
15110 return BSON.calculateObjectSize(object, serializeFunctions);
1512}
1513
1514/**
1515 * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization.
1516 *
1517 * @param {Object} object the Javascript object to serialize.
1518 * @param {Boolean} checkKeys the serializer will check if keys are valid.
1519 * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object.
1520 * @param {Number} index the index in the buffer where we wish to start serializing into.
1521 * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**.
1522 * @return {Number} returns the new write index in the Buffer.
1523 * @api public
1524 */
15251BSON.prototype.serializeWithBufferAndIndex = function(object, checkKeys, buffer, startIndex, serializeFunctions) {
15260 return BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, startIndex, serializeFunctions);
1527}
1528
1529/**
1530 * @ignore
1531 * @api private
1532 */
15331exports.Code = Code;
15341exports.Symbol = Symbol;
15351exports.BSON = BSON;
15361exports.DBRef = DBRef;
15371exports.Binary = Binary;
15381exports.ObjectID = ObjectID;
15391exports.Long = Long;
15401exports.Timestamp = Timestamp;
15411exports.Double = Double;
15421exports.MinKey = MinKey;
15431exports.MaxKey = MaxKey;
1544

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/code.js

37%
8
3
5
LineHitsSource
1/**
2 * A class representation of the BSON Code type.
3 *
4 * @class Represents the BSON Code type.
5 * @param {String|Function} code a string or function.
6 * @param {Object} [scope] an optional scope for the function.
7 * @return {Code}
8 */
91function Code(code, scope) {
100 if(!(this instanceof Code)) return new Code(code, scope);
11
120 this._bsontype = 'Code';
130 this.code = code;
140 this.scope = scope == null ? {} : scope;
15};
16
17/**
18 * @ignore
19 * @api private
20 */
211Code.prototype.toJSON = function() {
220 return {scope:this.scope, code:this.code};
23}
24
251exports.Code = Code;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js

33%
9
3
6
LineHitsSource
1/**
2 * A class representation of the BSON DBRef type.
3 *
4 * @class Represents the BSON DBRef type.
5 * @param {String} namespace the collection name.
6 * @param {ObjectID} oid the reference ObjectID.
7 * @param {String} [db] optional db name, if omitted the reference is local to the current db.
8 * @return {DBRef}
9 */
101function DBRef(namespace, oid, db) {
110 if(!(this instanceof DBRef)) return new DBRef(namespace, oid, db);
12
130 this._bsontype = 'DBRef';
140 this.namespace = namespace;
150 this.oid = oid;
160 this.db = db;
17};
18
19/**
20 * @ignore
21 * @api private
22 */
231DBRef.prototype.toJSON = function() {
240 return {
25 '$ref':this.namespace,
26 '$id':this.oid,
27 '$db':this.db == null ? '' : this.db
28 };
29}
30
311exports.DBRef = DBRef;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/double.js

44%
9
4
5
LineHitsSource
1/**
2 * A class representation of the BSON Double type.
3 *
4 * @class Represents the BSON Double type.
5 * @param {Number} value the number we want to represent as a double.
6 * @return {Double}
7 */
81function Double(value) {
90 if(!(this instanceof Double)) return new Double(value);
10
110 this._bsontype = 'Double';
120 this.value = value;
13}
14
15/**
16 * Access the number value.
17 *
18 * @return {Number} returns the wrapped double number.
19 * @api public
20 */
211Double.prototype.valueOf = function() {
220 return this.value;
23};
24
25/**
26 * @ignore
27 * @api private
28 */
291Double.prototype.toJSON = function() {
300 return this.value;
31}
32
331exports.Double = Double;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js

8%
49
4
45
LineHitsSource
1// Copyright (c) 2008, Fair Oaks Labs, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
15// may be used to endorse or promote products derived from this software
16// without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30//
31// Modifications to writeIEEE754 to support negative zeroes made by Brian White
32
331var readIEEE754 = function(buffer, offset, endian, mLen, nBytes) {
340 var e, m,
35 bBE = (endian === 'big'),
36 eLen = nBytes * 8 - mLen - 1,
37 eMax = (1 << eLen) - 1,
38 eBias = eMax >> 1,
39 nBits = -7,
40 i = bBE ? 0 : (nBytes - 1),
41 d = bBE ? 1 : -1,
42 s = buffer[offset + i];
43
440 i += d;
45
460 e = s & ((1 << (-nBits)) - 1);
470 s >>= (-nBits);
480 nBits += eLen;
490 for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
50
510 m = e & ((1 << (-nBits)) - 1);
520 e >>= (-nBits);
530 nBits += mLen;
540 for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
55
560 if (e === 0) {
570 e = 1 - eBias;
580 } else if (e === eMax) {
590 return m ? NaN : ((s ? -1 : 1) * Infinity);
60 } else {
610 m = m + Math.pow(2, mLen);
620 e = e - eBias;
63 }
640 return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
65};
66
671var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) {
680 var e, m, c,
69 bBE = (endian === 'big'),
70 eLen = nBytes * 8 - mLen - 1,
71 eMax = (1 << eLen) - 1,
72 eBias = eMax >> 1,
73 rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
74 i = bBE ? (nBytes-1) : 0,
75 d = bBE ? -1 : 1,
76 s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
77
780 value = Math.abs(value);
79
800 if (isNaN(value) || value === Infinity) {
810 m = isNaN(value) ? 1 : 0;
820 e = eMax;
83 } else {
840 e = Math.floor(Math.log(value) / Math.LN2);
850 if (value * (c = Math.pow(2, -e)) < 1) {
860 e--;
870 c *= 2;
88 }
890 if (e+eBias >= 1) {
900 value += rt / c;
91 } else {
920 value += rt * Math.pow(2, 1 - eBias);
93 }
940 if (value * c >= 2) {
950 e++;
960 c /= 2;
97 }
98
990 if (e + eBias >= eMax) {
1000 m = 0;
1010 e = eMax;
1020 } else if (e + eBias >= 1) {
1030 m = (value * c - 1) * Math.pow(2, mLen);
1040 e = e + eBias;
105 } else {
1060 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
1070 e = 0;
108 }
109 }
110
1110 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
112
1130 e = (e << mLen) | m;
1140 eLen += mLen;
1150 for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
116
1170 buffer[offset + i - d] |= s * 128;
118};
119
1201exports.readIEEE754 = readIEEE754;
1211exports.writeIEEE754 = writeIEEE754;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/index.js

42%
21
9
12
LineHitsSource
11try {
21 exports.BSONPure = require('./bson');
31 exports.BSONNative = require('../../ext');
4} catch(err) {
5 // do nothing
6}
7
81[ './binary_parser'
9 , './binary'
10 , './code'
11 , './db_ref'
12 , './double'
13 , './max_key'
14 , './min_key'
15 , './objectid'
16 , './symbol'
17 , './timestamp'
18 , './long'].forEach(function (path) {
1911 var module = require('./' + path);
2011 for (var i in module) {
2112 exports[i] = module[i];
22 }
23});
24
25// Exports all the classes for the NATIVE JS BSON Parser
261exports.native = function() {
270 var classes = {};
28 // Map all the classes
290 [ './binary_parser'
30 , './binary'
31 , './code'
32 , './db_ref'
33 , './double'
34 , './max_key'
35 , './min_key'
36 , './objectid'
37 , './symbol'
38 , './timestamp'
39 , './long'
40 , '../../ext'
41].forEach(function (path) {
420 var module = require('./' + path);
430 for (var i in module) {
440 classes[i] = module[i];
45 }
46 });
47 // Return classes list
480 return classes;
49}
50
51// Exports all the classes for the PURE JS BSON Parser
521exports.pure = function() {
530 var classes = {};
54 // Map all the classes
550 [ './binary_parser'
56 , './binary'
57 , './code'
58 , './db_ref'
59 , './double'
60 , './max_key'
61 , './min_key'
62 , './objectid'
63 , './symbol'
64 , './timestamp'
65 , './long'
66 , '././bson'].forEach(function (path) {
670 var module = require('./' + path);
680 for (var i in module) {
690 classes[i] = module[i];
70 }
71 });
72 // Return classes list
730 return classes;
74}
75

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/long.js

31%
296
94
202
LineHitsSource
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// Copyright 2009 Google Inc. All Rights Reserved
14
15/**
16 * Defines a Long class for representing a 64-bit two's-complement
17 * integer value, which faithfully simulates the behavior of a Java "Long". This
18 * implementation is derived from LongLib in GWT.
19 *
20 * Constructs a 64-bit two's-complement integer, given its low and high 32-bit
21 * values as *signed* integers. See the from* functions below for more
22 * convenient ways of constructing Longs.
23 *
24 * The internal representation of a Long is the two given signed, 32-bit values.
25 * We use 32-bit pieces because these are the size of integers on which
26 * Javascript performs bit-operations. For operations like addition and
27 * multiplication, we split each number into 16-bit pieces, which can easily be
28 * multiplied within Javascript's floating-point representation without overflow
29 * or change in sign.
30 *
31 * In the algorithms below, we frequently reduce the negative case to the
32 * positive case by negating the input(s) and then post-processing the result.
33 * Note that we must ALWAYS check specially whether those values are MIN_VALUE
34 * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
35 * a positive number, it overflows back into a negative). Not handling this
36 * case would often result in infinite recursion.
37 *
38 * @class Represents the BSON Long type.
39 * @param {Number} low the low (signed) 32 bits of the Long.
40 * @param {Number} high the high (signed) 32 bits of the Long.
41 */
421function Long(low, high) {
4310 if(!(this instanceof Long)) return new Long(low, high);
44
4510 this._bsontype = 'Long';
46 /**
47 * @type {number}
48 * @api private
49 */
5010 this.low_ = low | 0; // force into 32 signed bits.
51
52 /**
53 * @type {number}
54 * @api private
55 */
5610 this.high_ = high | 0; // force into 32 signed bits.
57};
58
59/**
60 * Return the int value.
61 *
62 * @return {Number} the value, assuming it is a 32-bit integer.
63 * @api public
64 */
651Long.prototype.toInt = function() {
660 return this.low_;
67};
68
69/**
70 * Return the Number value.
71 *
72 * @return {Number} the closest floating-point representation to this value.
73 * @api public
74 */
751Long.prototype.toNumber = function() {
760 return this.high_ * Long.TWO_PWR_32_DBL_ +
77 this.getLowBitsUnsigned();
78};
79
80/**
81 * Return the JSON value.
82 *
83 * @return {String} the JSON representation.
84 * @api public
85 */
861Long.prototype.toJSON = function() {
870 return this.toString();
88}
89
90/**
91 * Return the String value.
92 *
93 * @param {Number} [opt_radix] the radix in which the text should be written.
94 * @return {String} the textual representation of this value.
95 * @api public
96 */
971Long.prototype.toString = function(opt_radix) {
980 var radix = opt_radix || 10;
990 if (radix < 2 || 36 < radix) {
1000 throw Error('radix out of range: ' + radix);
101 }
102
1030 if (this.isZero()) {
1040 return '0';
105 }
106
1070 if (this.isNegative()) {
1080 if (this.equals(Long.MIN_VALUE)) {
109 // We need to change the Long value before it can be negated, so we remove
110 // the bottom-most digit in this base and then recurse to do the rest.
1110 var radixLong = Long.fromNumber(radix);
1120 var div = this.div(radixLong);
1130 var rem = div.multiply(radixLong).subtract(this);
1140 return div.toString(radix) + rem.toInt().toString(radix);
115 } else {
1160 return '-' + this.negate().toString(radix);
117 }
118 }
119
120 // Do several (6) digits each time through the loop, so as to
121 // minimize the calls to the very expensive emulated div.
1220 var radixToPower = Long.fromNumber(Math.pow(radix, 6));
123
1240 var rem = this;
1250 var result = '';
1260 while (true) {
1270 var remDiv = rem.div(radixToPower);
1280 var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
1290 var digits = intval.toString(radix);
130
1310 rem = remDiv;
1320 if (rem.isZero()) {
1330 return digits + result;
134 } else {
1350 while (digits.length < 6) {
1360 digits = '0' + digits;
137 }
1380 result = '' + digits + result;
139 }
140 }
141};
142
143/**
144 * Return the high 32-bits value.
145 *
146 * @return {Number} the high 32-bits as a signed value.
147 * @api public
148 */
1491Long.prototype.getHighBits = function() {
1500 return this.high_;
151};
152
153/**
154 * Return the low 32-bits value.
155 *
156 * @return {Number} the low 32-bits as a signed value.
157 * @api public
158 */
1591Long.prototype.getLowBits = function() {
1600 return this.low_;
161};
162
163/**
164 * Return the low unsigned 32-bits value.
165 *
166 * @return {Number} the low 32-bits as an unsigned value.
167 * @api public
168 */
1691Long.prototype.getLowBitsUnsigned = function() {
1700 return (this.low_ >= 0) ?
171 this.low_ : Long.TWO_PWR_32_DBL_ + this.low_;
172};
173
174/**
175 * Returns the number of bits needed to represent the absolute value of this Long.
176 *
177 * @return {Number} Returns the number of bits needed to represent the absolute value of this Long.
178 * @api public
179 */
1801Long.prototype.getNumBitsAbs = function() {
1810 if (this.isNegative()) {
1820 if (this.equals(Long.MIN_VALUE)) {
1830 return 64;
184 } else {
1850 return this.negate().getNumBitsAbs();
186 }
187 } else {
1880 var val = this.high_ != 0 ? this.high_ : this.low_;
1890 for (var bit = 31; bit > 0; bit--) {
1900 if ((val & (1 << bit)) != 0) {
1910 break;
192 }
193 }
1940 return this.high_ != 0 ? bit + 33 : bit + 1;
195 }
196};
197
198/**
199 * Return whether this value is zero.
200 *
201 * @return {Boolean} whether this value is zero.
202 * @api public
203 */
2041Long.prototype.isZero = function() {
2050 return this.high_ == 0 && this.low_ == 0;
206};
207
208/**
209 * Return whether this value is negative.
210 *
211 * @return {Boolean} whether this value is negative.
212 * @api public
213 */
2141Long.prototype.isNegative = function() {
2150 return this.high_ < 0;
216};
217
218/**
219 * Return whether this value is odd.
220 *
221 * @return {Boolean} whether this value is odd.
222 * @api public
223 */
2241Long.prototype.isOdd = function() {
2250 return (this.low_ & 1) == 1;
226};
227
228/**
229 * Return whether this Long equals the other
230 *
231 * @param {Long} other Long to compare against.
232 * @return {Boolean} whether this Long equals the other
233 * @api public
234 */
2351Long.prototype.equals = function(other) {
2361 return (this.high_ == other.high_) && (this.low_ == other.low_);
237};
238
239/**
240 * Return whether this Long does not equal the other.
241 *
242 * @param {Long} other Long to compare against.
243 * @return {Boolean} whether this Long does not equal the other.
244 * @api public
245 */
2461Long.prototype.notEquals = function(other) {
2470 return (this.high_ != other.high_) || (this.low_ != other.low_);
248};
249
250/**
251 * Return whether this Long is less than the other.
252 *
253 * @param {Long} other Long to compare against.
254 * @return {Boolean} whether this Long is less than the other.
255 * @api public
256 */
2571Long.prototype.lessThan = function(other) {
2580 return this.compare(other) < 0;
259};
260
261/**
262 * Return whether this Long is less than or equal to the other.
263 *
264 * @param {Long} other Long to compare against.
265 * @return {Boolean} whether this Long is less than or equal to the other.
266 * @api public
267 */
2681Long.prototype.lessThanOrEqual = function(other) {
2690 return this.compare(other) <= 0;
270};
271
272/**
273 * Return whether this Long is greater than the other.
274 *
275 * @param {Long} other Long to compare against.
276 * @return {Boolean} whether this Long is greater than the other.
277 * @api public
278 */
2791Long.prototype.greaterThan = function(other) {
2800 return this.compare(other) > 0;
281};
282
283/**
284 * Return whether this Long is greater than or equal to the other.
285 *
286 * @param {Long} other Long to compare against.
287 * @return {Boolean} whether this Long is greater than or equal to the other.
288 * @api public
289 */
2901Long.prototype.greaterThanOrEqual = function(other) {
2910 return this.compare(other) >= 0;
292};
293
294/**
295 * Compares this Long with the given one.
296 *
297 * @param {Long} other Long to compare against.
298 * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater.
299 * @api public
300 */
3011Long.prototype.compare = function(other) {
3020 if (this.equals(other)) {
3030 return 0;
304 }
305
3060 var thisNeg = this.isNegative();
3070 var otherNeg = other.isNegative();
3080 if (thisNeg && !otherNeg) {
3090 return -1;
310 }
3110 if (!thisNeg && otherNeg) {
3120 return 1;
313 }
314
315 // at this point, the signs are the same, so subtraction will not overflow
3160 if (this.subtract(other).isNegative()) {
3170 return -1;
318 } else {
3190 return 1;
320 }
321};
322
323/**
324 * The negation of this value.
325 *
326 * @return {Long} the negation of this value.
327 * @api public
328 */
3291Long.prototype.negate = function() {
3301 if (this.equals(Long.MIN_VALUE)) {
3310 return Long.MIN_VALUE;
332 } else {
3331 return this.not().add(Long.ONE);
334 }
335};
336
337/**
338 * Returns the sum of this and the given Long.
339 *
340 * @param {Long} other Long to add to this one.
341 * @return {Long} the sum of this and the given Long.
342 * @api public
343 */
3441Long.prototype.add = function(other) {
345 // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
346
3471 var a48 = this.high_ >>> 16;
3481 var a32 = this.high_ & 0xFFFF;
3491 var a16 = this.low_ >>> 16;
3501 var a00 = this.low_ & 0xFFFF;
351
3521 var b48 = other.high_ >>> 16;
3531 var b32 = other.high_ & 0xFFFF;
3541 var b16 = other.low_ >>> 16;
3551 var b00 = other.low_ & 0xFFFF;
356
3571 var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
3581 c00 += a00 + b00;
3591 c16 += c00 >>> 16;
3601 c00 &= 0xFFFF;
3611 c16 += a16 + b16;
3621 c32 += c16 >>> 16;
3631 c16 &= 0xFFFF;
3641 c32 += a32 + b32;
3651 c48 += c32 >>> 16;
3661 c32 &= 0xFFFF;
3671 c48 += a48 + b48;
3681 c48 &= 0xFFFF;
3691 return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
370};
371
372/**
373 * Returns the difference of this and the given Long.
374 *
375 * @param {Long} other Long to subtract from this.
376 * @return {Long} the difference of this and the given Long.
377 * @api public
378 */
3791Long.prototype.subtract = function(other) {
3800 return this.add(other.negate());
381};
382
383/**
384 * Returns the product of this and the given Long.
385 *
386 * @param {Long} other Long to multiply with this.
387 * @return {Long} the product of this and the other.
388 * @api public
389 */
3901Long.prototype.multiply = function(other) {
3910 if (this.isZero()) {
3920 return Long.ZERO;
3930 } else if (other.isZero()) {
3940 return Long.ZERO;
395 }
396
3970 if (this.equals(Long.MIN_VALUE)) {
3980 return other.isOdd() ? Long.MIN_VALUE : Long.ZERO;
3990 } else if (other.equals(Long.MIN_VALUE)) {
4000 return this.isOdd() ? Long.MIN_VALUE : Long.ZERO;
401 }
402
4030 if (this.isNegative()) {
4040 if (other.isNegative()) {
4050 return this.negate().multiply(other.negate());
406 } else {
4070 return this.negate().multiply(other).negate();
408 }
4090 } else if (other.isNegative()) {
4100 return this.multiply(other.negate()).negate();
411 }
412
413 // If both Longs are small, use float multiplication
4140 if (this.lessThan(Long.TWO_PWR_24_) &&
415 other.lessThan(Long.TWO_PWR_24_)) {
4160 return Long.fromNumber(this.toNumber() * other.toNumber());
417 }
418
419 // Divide each Long into 4 chunks of 16 bits, and then add up 4x4 products.
420 // We can skip products that would overflow.
421
4220 var a48 = this.high_ >>> 16;
4230 var a32 = this.high_ & 0xFFFF;
4240 var a16 = this.low_ >>> 16;
4250 var a00 = this.low_ & 0xFFFF;
426
4270 var b48 = other.high_ >>> 16;
4280 var b32 = other.high_ & 0xFFFF;
4290 var b16 = other.low_ >>> 16;
4300 var b00 = other.low_ & 0xFFFF;
431
4320 var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
4330 c00 += a00 * b00;
4340 c16 += c00 >>> 16;
4350 c00 &= 0xFFFF;
4360 c16 += a16 * b00;
4370 c32 += c16 >>> 16;
4380 c16 &= 0xFFFF;
4390 c16 += a00 * b16;
4400 c32 += c16 >>> 16;
4410 c16 &= 0xFFFF;
4420 c32 += a32 * b00;
4430 c48 += c32 >>> 16;
4440 c32 &= 0xFFFF;
4450 c32 += a16 * b16;
4460 c48 += c32 >>> 16;
4470 c32 &= 0xFFFF;
4480 c32 += a00 * b32;
4490 c48 += c32 >>> 16;
4500 c32 &= 0xFFFF;
4510 c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
4520 c48 &= 0xFFFF;
4530 return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
454};
455
456/**
457 * Returns this Long divided by the given one.
458 *
459 * @param {Long} other Long by which to divide.
460 * @return {Long} this Long divided by the given one.
461 * @api public
462 */
4631Long.prototype.div = function(other) {
4640 if (other.isZero()) {
4650 throw Error('division by zero');
4660 } else if (this.isZero()) {
4670 return Long.ZERO;
468 }
469
4700 if (this.equals(Long.MIN_VALUE)) {
4710 if (other.equals(Long.ONE) ||
472 other.equals(Long.NEG_ONE)) {
4730 return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
4740 } else if (other.equals(Long.MIN_VALUE)) {
4750 return Long.ONE;
476 } else {
477 // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
4780 var halfThis = this.shiftRight(1);
4790 var approx = halfThis.div(other).shiftLeft(1);
4800 if (approx.equals(Long.ZERO)) {
4810 return other.isNegative() ? Long.ONE : Long.NEG_ONE;
482 } else {
4830 var rem = this.subtract(other.multiply(approx));
4840 var result = approx.add(rem.div(other));
4850 return result;
486 }
487 }
4880 } else if (other.equals(Long.MIN_VALUE)) {
4890 return Long.ZERO;
490 }
491
4920 if (this.isNegative()) {
4930 if (other.isNegative()) {
4940 return this.negate().div(other.negate());
495 } else {
4960 return this.negate().div(other).negate();
497 }
4980 } else if (other.isNegative()) {
4990 return this.div(other.negate()).negate();
500 }
501
502 // Repeat the following until the remainder is less than other: find a
503 // floating-point that approximates remainder / other *from below*, add this
504 // into the result, and subtract it from the remainder. It is critical that
505 // the approximate value is less than or equal to the real value so that the
506 // remainder never becomes negative.
5070 var res = Long.ZERO;
5080 var rem = this;
5090 while (rem.greaterThanOrEqual(other)) {
510 // Approximate the result of division. This may be a little greater or
511 // smaller than the actual value.
5120 var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
513
514 // We will tweak the approximate result by changing it in the 48-th digit or
515 // the smallest non-fractional digit, whichever is larger.
5160 var log2 = Math.ceil(Math.log(approx) / Math.LN2);
5170 var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
518
519 // Decrease the approximation until it is smaller than the remainder. Note
520 // that if it is too large, the product overflows and is negative.
5210 var approxRes = Long.fromNumber(approx);
5220 var approxRem = approxRes.multiply(other);
5230 while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
5240 approx -= delta;
5250 approxRes = Long.fromNumber(approx);
5260 approxRem = approxRes.multiply(other);
527 }
528
529 // We know the answer can't be zero... and actually, zero would cause
530 // infinite recursion since we would make no progress.
5310 if (approxRes.isZero()) {
5320 approxRes = Long.ONE;
533 }
534
5350 res = res.add(approxRes);
5360 rem = rem.subtract(approxRem);
537 }
5380 return res;
539};
540
541/**
542 * Returns this Long modulo the given one.
543 *
544 * @param {Long} other Long by which to mod.
545 * @return {Long} this Long modulo the given one.
546 * @api public
547 */
5481Long.prototype.modulo = function(other) {
5490 return this.subtract(this.div(other).multiply(other));
550};
551
552/**
553 * The bitwise-NOT of this value.
554 *
555 * @return {Long} the bitwise-NOT of this value.
556 * @api public
557 */
5581Long.prototype.not = function() {
5591 return Long.fromBits(~this.low_, ~this.high_);
560};
561
562/**
563 * Returns the bitwise-AND of this Long and the given one.
564 *
565 * @param {Long} other the Long with which to AND.
566 * @return {Long} the bitwise-AND of this and the other.
567 * @api public
568 */
5691Long.prototype.and = function(other) {
5700 return Long.fromBits(this.low_ & other.low_, this.high_ & other.high_);
571};
572
573/**
574 * Returns the bitwise-OR of this Long and the given one.
575 *
576 * @param {Long} other the Long with which to OR.
577 * @return {Long} the bitwise-OR of this and the other.
578 * @api public
579 */
5801Long.prototype.or = function(other) {
5810 return Long.fromBits(this.low_ | other.low_, this.high_ | other.high_);
582};
583
584/**
585 * Returns the bitwise-XOR of this Long and the given one.
586 *
587 * @param {Long} other the Long with which to XOR.
588 * @return {Long} the bitwise-XOR of this and the other.
589 * @api public
590 */
5911Long.prototype.xor = function(other) {
5920 return Long.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_);
593};
594
595/**
596 * Returns this Long with bits shifted to the left by the given amount.
597 *
598 * @param {Number} numBits the number of bits by which to shift.
599 * @return {Long} this shifted to the left by the given amount.
600 * @api public
601 */
6021Long.prototype.shiftLeft = function(numBits) {
6030 numBits &= 63;
6040 if (numBits == 0) {
6050 return this;
606 } else {
6070 var low = this.low_;
6080 if (numBits < 32) {
6090 var high = this.high_;
6100 return Long.fromBits(
611 low << numBits,
612 (high << numBits) | (low >>> (32 - numBits)));
613 } else {
6140 return Long.fromBits(0, low << (numBits - 32));
615 }
616 }
617};
618
619/**
620 * Returns this Long with bits shifted to the right by the given amount.
621 *
622 * @param {Number} numBits the number of bits by which to shift.
623 * @return {Long} this shifted to the right by the given amount.
624 * @api public
625 */
6261Long.prototype.shiftRight = function(numBits) {
6270 numBits &= 63;
6280 if (numBits == 0) {
6290 return this;
630 } else {
6310 var high = this.high_;
6320 if (numBits < 32) {
6330 var low = this.low_;
6340 return Long.fromBits(
635 (low >>> numBits) | (high << (32 - numBits)),
636 high >> numBits);
637 } else {
6380 return Long.fromBits(
639 high >> (numBits - 32),
640 high >= 0 ? 0 : -1);
641 }
642 }
643};
644
645/**
646 * Returns this Long with bits shifted to the right by the given amount, with the new top bits matching the current sign bit.
647 *
648 * @param {Number} numBits the number of bits by which to shift.
649 * @return {Long} this shifted to the right by the given amount, with zeros placed into the new leading bits.
650 * @api public
651 */
6521Long.prototype.shiftRightUnsigned = function(numBits) {
6530 numBits &= 63;
6540 if (numBits == 0) {
6550 return this;
656 } else {
6570 var high = this.high_;
6580 if (numBits < 32) {
6590 var low = this.low_;
6600 return Long.fromBits(
661 (low >>> numBits) | (high << (32 - numBits)),
662 high >>> numBits);
6630 } else if (numBits == 32) {
6640 return Long.fromBits(high, 0);
665 } else {
6660 return Long.fromBits(high >>> (numBits - 32), 0);
667 }
668 }
669};
670
671/**
672 * Returns a Long representing the given (32-bit) integer value.
673 *
674 * @param {Number} value the 32-bit integer in question.
675 * @return {Long} the corresponding Long value.
676 * @api public
677 */
6781Long.fromInt = function(value) {
6794 if (-128 <= value && value < 128) {
6803 var cachedObj = Long.INT_CACHE_[value];
6813 if (cachedObj) {
6820 return cachedObj;
683 }
684 }
685
6864 var obj = new Long(value | 0, value < 0 ? -1 : 0);
6874 if (-128 <= value && value < 128) {
6883 Long.INT_CACHE_[value] = obj;
689 }
6904 return obj;
691};
692
693/**
694 * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
695 *
696 * @param {Number} value the number in question.
697 * @return {Long} the corresponding Long value.
698 * @api public
699 */
7001Long.fromNumber = function(value) {
7013 if (isNaN(value) || !isFinite(value)) {
7020 return Long.ZERO;
7033 } else if (value <= -Long.TWO_PWR_63_DBL_) {
7040 return Long.MIN_VALUE;
7053 } else if (value + 1 >= Long.TWO_PWR_63_DBL_) {
7060 return Long.MAX_VALUE;
7073 } else if (value < 0) {
7081 return Long.fromNumber(-value).negate();
709 } else {
7102 return new Long(
711 (value % Long.TWO_PWR_32_DBL_) | 0,
712 (value / Long.TWO_PWR_32_DBL_) | 0);
713 }
714};
715
716/**
717 * Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits.
718 *
719 * @param {Number} lowBits the low 32-bits.
720 * @param {Number} highBits the high 32-bits.
721 * @return {Long} the corresponding Long value.
722 * @api public
723 */
7241Long.fromBits = function(lowBits, highBits) {
7254 return new Long(lowBits, highBits);
726};
727
728/**
729 * Returns a Long representation of the given string, written using the given radix.
730 *
731 * @param {String} str the textual representation of the Long.
732 * @param {Number} opt_radix the radix in which the text is written.
733 * @return {Long} the corresponding Long value.
734 * @api public
735 */
7361Long.fromString = function(str, opt_radix) {
7370 if (str.length == 0) {
7380 throw Error('number format error: empty string');
739 }
740
7410 var radix = opt_radix || 10;
7420 if (radix < 2 || 36 < radix) {
7430 throw Error('radix out of range: ' + radix);
744 }
745
7460 if (str.charAt(0) == '-') {
7470 return Long.fromString(str.substring(1), radix).negate();
7480 } else if (str.indexOf('-') >= 0) {
7490 throw Error('number format error: interior "-" character: ' + str);
750 }
751
752 // Do several (8) digits each time through the loop, so as to
753 // minimize the calls to the very expensive emulated div.
7540 var radixToPower = Long.fromNumber(Math.pow(radix, 8));
755
7560 var result = Long.ZERO;
7570 for (var i = 0; i < str.length; i += 8) {
7580 var size = Math.min(8, str.length - i);
7590 var value = parseInt(str.substring(i, i + size), radix);
7600 if (size < 8) {
7610 var power = Long.fromNumber(Math.pow(radix, size));
7620 result = result.multiply(power).add(Long.fromNumber(value));
763 } else {
7640 result = result.multiply(radixToPower);
7650 result = result.add(Long.fromNumber(value));
766 }
767 }
7680 return result;
769};
770
771// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
772// from* methods on which they depend.
773
774
775/**
776 * A cache of the Long representations of small integer values.
777 * @type {Object}
778 * @api private
779 */
7801Long.INT_CACHE_ = {};
781
782// NOTE: the compiler should inline these constant values below and then remove
783// these variables, so there should be no runtime penalty for these.
784
785/**
786 * Number used repeated below in calculations. This must appear before the
787 * first call to any from* function below.
788 * @type {number}
789 * @api private
790 */
7911Long.TWO_PWR_16_DBL_ = 1 << 16;
792
793/**
794 * @type {number}
795 * @api private
796 */
7971Long.TWO_PWR_24_DBL_ = 1 << 24;
798
799/**
800 * @type {number}
801 * @api private
802 */
8031Long.TWO_PWR_32_DBL_ = Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_;
804
805/**
806 * @type {number}
807 * @api private
808 */
8091Long.TWO_PWR_31_DBL_ = Long.TWO_PWR_32_DBL_ / 2;
810
811/**
812 * @type {number}
813 * @api private
814 */
8151Long.TWO_PWR_48_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_;
816
817/**
818 * @type {number}
819 * @api private
820 */
8211Long.TWO_PWR_64_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_;
822
823/**
824 * @type {number}
825 * @api private
826 */
8271Long.TWO_PWR_63_DBL_ = Long.TWO_PWR_64_DBL_ / 2;
828
829/** @type {Long} */
8301Long.ZERO = Long.fromInt(0);
831
832/** @type {Long} */
8331Long.ONE = Long.fromInt(1);
834
835/** @type {Long} */
8361Long.NEG_ONE = Long.fromInt(-1);
837
838/** @type {Long} */
8391Long.MAX_VALUE =
840 Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0);
841
842/** @type {Long} */
8431Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0);
844
845/**
846 * @type {Long}
847 * @api private
848 */
8491Long.TWO_PWR_24_ = Long.fromInt(1 << 24);
850
851/**
852 * Expose.
853 */
8541exports.Long = Long;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js

50%
4
2
2
LineHitsSource
1/**
2 * A class representation of the BSON MaxKey type.
3 *
4 * @class Represents the BSON MaxKey type.
5 * @return {MaxKey}
6 */
71function MaxKey() {
80 if(!(this instanceof MaxKey)) return new MaxKey();
9
100 this._bsontype = 'MaxKey';
11}
12
131exports.MaxKey = MaxKey;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js

50%
4
2
2
LineHitsSource
1/**
2 * A class representation of the BSON MinKey type.
3 *
4 * @class Represents the BSON MinKey type.
5 * @return {MinKey}
6 */
71function MinKey() {
80 if(!(this instanceof MinKey)) return new MinKey();
9
100 this._bsontype = 'MinKey';
11}
12
131exports.MinKey = MinKey;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js

27%
76
21
55
LineHitsSource
1/**
2 * Module dependencies.
3 */
41var BinaryParser = require('./binary_parser').BinaryParser;
5
6/**
7 * Machine id.
8 *
9 * Create a random 3-byte value (i.e. unique for this
10 * process). Other drivers use a md5 of the machine id here, but
11 * that would mean an asyc call to gethostname, so we don't bother.
12 */
131var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10);
14
15// Regular expression that checks for hex value
161var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");
17
18/**
19* Create a new ObjectID instance
20*
21* @class Represents the BSON ObjectID type
22* @param {String|Number} id Can be a 24 byte hex string, 12 byte binary string or a Number.
23* @return {Object} instance of ObjectID.
24*/
251var ObjectID = function ObjectID(id) {
260 if(!(this instanceof ObjectID)) return new ObjectID(id);
27
280 this._bsontype = 'ObjectID';
290 var __id = null;
30
31 // Throw an error if it's not a valid setup
320 if(id != null && 'number' != typeof id && (id.length != 12 && id.length != 24))
330 throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters");
34
35 // Generate id based on the input
360 if(id == null || typeof id == 'number') {
37 // convert to 12 byte binary string
380 this.id = this.generate(id);
390 } else if(id != null && id.length === 12) {
40 // assume 12 byte string
410 this.id = id;
420 } else if(checkForHexRegExp.test(id)) {
430 return ObjectID.createFromHexString(id);
44 } else {
450 throw new Error("Value passed in is not a valid 24 character hex string");
46 }
47
480 if(ObjectID.cacheHexString) this.__id = this.toHexString();
49};
50
51// Allow usage of ObjectId aswell as ObjectID
521var ObjectId = ObjectID;
53
54/**
55* Return the ObjectID id as a 24 byte hex string representation
56*
57* @return {String} return the 24 byte hex string representation.
58* @api public
59*/
601ObjectID.prototype.toHexString = function() {
610 if(ObjectID.cacheHexString && this.__id) return this.__id;
62
630 var hexString = ''
64 , number
65 , value;
66
670 for (var index = 0, len = this.id.length; index < len; index++) {
680 value = BinaryParser.toByte(this.id[index]);
690 number = value <= 15
70 ? '0' + value.toString(16)
71 : value.toString(16);
720 hexString = hexString + number;
73 }
74
750 if(ObjectID.cacheHexString) this.__id = hexString;
760 return hexString;
77};
78
79/**
80* Update the ObjectID index used in generating new ObjectID's on the driver
81*
82* @return {Number} returns next index value.
83* @api private
84*/
851ObjectID.prototype.get_inc = function() {
860 return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF;
87};
88
89/**
90* Update the ObjectID index used in generating new ObjectID's on the driver
91*
92* @return {Number} returns next index value.
93* @api private
94*/
951ObjectID.prototype.getInc = function() {
960 return this.get_inc();
97};
98
99/**
100* Generate a 12 byte id string used in ObjectID's
101*
102* @param {Number} [time] optional parameter allowing to pass in a second based timestamp.
103* @return {String} return the 12 byte id binary string.
104* @api private
105*/
1061ObjectID.prototype.generate = function(time) {
1070 if ('number' != typeof time) {
1080 time = parseInt(Date.now()/1000,10);
109 }
110
1110 var time4Bytes = BinaryParser.encodeInt(time, 32, true, true);
112 /* for time-based ObjectID the bytes following the time will be zeroed */
1130 var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false);
1140 var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid);
1150 var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true);
116
1170 return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes;
118};
119
120/**
121* Converts the id into a 24 byte hex string for printing
122*
123* @return {String} return the 24 byte hex string representation.
124* @api private
125*/
1261ObjectID.prototype.toString = function() {
1270 return this.toHexString();
128};
129
130/**
131* Converts to a string representation of this Id.
132*
133* @return {String} return the 24 byte hex string representation.
134* @api private
135*/
1361ObjectID.prototype.inspect = ObjectID.prototype.toString;
137
138/**
139* Converts to its JSON representation.
140*
141* @return {String} return the 24 byte hex string representation.
142* @api private
143*/
1441ObjectID.prototype.toJSON = function() {
1450 return this.toHexString();
146};
147
148/**
149* Compares the equality of this ObjectID with `otherID`.
150*
151* @param {Object} otherID ObjectID instance to compare against.
152* @return {Bool} the result of comparing two ObjectID's
153* @api public
154*/
1551ObjectID.prototype.equals = function equals (otherID) {
1560 var id = (otherID instanceof ObjectID || otherID.toHexString)
157 ? otherID.id
158 : ObjectID.createFromHexString(otherID).id;
159
1600 return this.id === id;
161}
162
163/**
164* Returns the generation date (accurate up to the second) that this ID was generated.
165*
166* @return {Date} the generation date
167* @api public
168*/
1691ObjectID.prototype.getTimestamp = function() {
1700 var timestamp = new Date();
1710 timestamp.setTime(Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)) * 1000);
1720 return timestamp;
173}
174
175/**
176* @ignore
177* @api private
178*/
1791ObjectID.index = parseInt(Math.random() * 0xFFFFFF, 10);
180
1811ObjectID.createPk = function createPk () {
1820 return new ObjectID();
183};
184
185/**
186* Creates an ObjectID from a second based number, with the rest of the ObjectID zeroed out. Used for comparisons or sorting the ObjectID.
187*
188* @param {Number} time an integer number representing a number of seconds.
189* @return {ObjectID} return the created ObjectID
190* @api public
191*/
1921ObjectID.createFromTime = function createFromTime (time) {
1930 var id = BinaryParser.encodeInt(time, 32, true, true) +
194 BinaryParser.encodeInt(0, 64, true, true);
1950 return new ObjectID(id);
196};
197
198/**
199* Creates an ObjectID from a hex string representation of an ObjectID.
200*
201* @param {String} hexString create a ObjectID from a passed in 24 byte hexstring.
202* @return {ObjectID} return the created ObjectID
203* @api public
204*/
2051ObjectID.createFromHexString = function createFromHexString (hexString) {
206 // Throw an error if it's not a valid setup
2070 if(typeof hexString === 'undefined' || hexString != null && hexString.length != 24)
2080 throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters");
209
2100 var len = hexString.length;
211
2120 if(len > 12*2) {
2130 throw new Error('Id cannot be longer than 12 bytes');
214 }
215
2160 var result = ''
217 , string
218 , number;
219
2200 for (var index = 0; index < len; index += 2) {
2210 string = hexString.substr(index, 2);
2220 number = parseInt(string, 16);
2230 result += BinaryParser.fromByte(number);
224 }
225
2260 return new ObjectID(result, hexString);
227};
228
229/**
230* @ignore
231*/
2321Object.defineProperty(ObjectID.prototype, "generationTime", {
233 enumerable: true
234 , get: function () {
2350 return Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true));
236 }
237 , set: function (value) {
2380 var value = BinaryParser.encodeInt(value, 32, true, true);
2390 this.id = value + this.id.substr(4);
240 // delete this.__id;
2410 this.toHexString();
242 }
243});
244
245/**
246 * Expose.
247 */
2481exports.ObjectID = ObjectID;
2491exports.ObjectId = ObjectID;
250

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js

46%
13
6
7
LineHitsSource
1/**
2 * A class representation of the BSON Symbol type.
3 *
4 * @class Represents the BSON Symbol type.
5 * @param {String} value the string representing the symbol.
6 * @return {Symbol}
7 */
81function Symbol(value) {
90 if(!(this instanceof Symbol)) return new Symbol(value);
100 this._bsontype = 'Symbol';
110 this.value = value;
12}
13
14/**
15 * Access the wrapped string value.
16 *
17 * @return {String} returns the wrapped string.
18 * @api public
19 */
201Symbol.prototype.valueOf = function() {
210 return this.value;
22};
23
24/**
25 * @ignore
26 * @api private
27 */
281Symbol.prototype.toString = function() {
290 return this.value;
30}
31
32/**
33 * @ignore
34 * @api private
35 */
361Symbol.prototype.inspect = function() {
370 return this.value;
38}
39
40/**
41 * @ignore
42 * @api private
43 */
441Symbol.prototype.toJSON = function() {
450 return this.value;
46}
47
481exports.Symbol = Symbol;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js

21%
296
63
233
LineHitsSource
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// Copyright 2009 Google Inc. All Rights Reserved
14
15/**
16 * Defines a Timestamp class for representing a 64-bit two's-complement
17 * integer value, which faithfully simulates the behavior of a Java "Timestamp". This
18 * implementation is derived from TimestampLib in GWT.
19 *
20 * Constructs a 64-bit two's-complement integer, given its low and high 32-bit
21 * values as *signed* integers. See the from* functions below for more
22 * convenient ways of constructing Timestamps.
23 *
24 * The internal representation of a Timestamp is the two given signed, 32-bit values.
25 * We use 32-bit pieces because these are the size of integers on which
26 * Javascript performs bit-operations. For operations like addition and
27 * multiplication, we split each number into 16-bit pieces, which can easily be
28 * multiplied within Javascript's floating-point representation without overflow
29 * or change in sign.
30 *
31 * In the algorithms below, we frequently reduce the negative case to the
32 * positive case by negating the input(s) and then post-processing the result.
33 * Note that we must ALWAYS check specially whether those values are MIN_VALUE
34 * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
35 * a positive number, it overflows back into a negative). Not handling this
36 * case would often result in infinite recursion.
37 *
38 * @class Represents the BSON Timestamp type.
39 * @param {Number} low the low (signed) 32 bits of the Timestamp.
40 * @param {Number} high the high (signed) 32 bits of the Timestamp.
41 */
421function Timestamp(low, high) {
436 if(!(this instanceof Timestamp)) return new Timestamp(low, high);
446 this._bsontype = 'Timestamp';
45 /**
46 * @type {number}
47 * @api private
48 */
496 this.low_ = low | 0; // force into 32 signed bits.
50
51 /**
52 * @type {number}
53 * @api private
54 */
556 this.high_ = high | 0; // force into 32 signed bits.
56};
57
58/**
59 * Return the int value.
60 *
61 * @return {Number} the value, assuming it is a 32-bit integer.
62 * @api public
63 */
641Timestamp.prototype.toInt = function() {
650 return this.low_;
66};
67
68/**
69 * Return the Number value.
70 *
71 * @return {Number} the closest floating-point representation to this value.
72 * @api public
73 */
741Timestamp.prototype.toNumber = function() {
750 return this.high_ * Timestamp.TWO_PWR_32_DBL_ +
76 this.getLowBitsUnsigned();
77};
78
79/**
80 * Return the JSON value.
81 *
82 * @return {String} the JSON representation.
83 * @api public
84 */
851Timestamp.prototype.toJSON = function() {
860 return this.toString();
87}
88
89/**
90 * Return the String value.
91 *
92 * @param {Number} [opt_radix] the radix in which the text should be written.
93 * @return {String} the textual representation of this value.
94 * @api public
95 */
961Timestamp.prototype.toString = function(opt_radix) {
970 var radix = opt_radix || 10;
980 if (radix < 2 || 36 < radix) {
990 throw Error('radix out of range: ' + radix);
100 }
101
1020 if (this.isZero()) {
1030 return '0';
104 }
105
1060 if (this.isNegative()) {
1070 if (this.equals(Timestamp.MIN_VALUE)) {
108 // We need to change the Timestamp value before it can be negated, so we remove
109 // the bottom-most digit in this base and then recurse to do the rest.
1100 var radixTimestamp = Timestamp.fromNumber(radix);
1110 var div = this.div(radixTimestamp);
1120 var rem = div.multiply(radixTimestamp).subtract(this);
1130 return div.toString(radix) + rem.toInt().toString(radix);
114 } else {
1150 return '-' + this.negate().toString(radix);
116 }
117 }
118
119 // Do several (6) digits each time through the loop, so as to
120 // minimize the calls to the very expensive emulated div.
1210 var radixToPower = Timestamp.fromNumber(Math.pow(radix, 6));
122
1230 var rem = this;
1240 var result = '';
1250 while (true) {
1260 var remDiv = rem.div(radixToPower);
1270 var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
1280 var digits = intval.toString(radix);
129
1300 rem = remDiv;
1310 if (rem.isZero()) {
1320 return digits + result;
133 } else {
1340 while (digits.length < 6) {
1350 digits = '0' + digits;
136 }
1370 result = '' + digits + result;
138 }
139 }
140};
141
142/**
143 * Return the high 32-bits value.
144 *
145 * @return {Number} the high 32-bits as a signed value.
146 * @api public
147 */
1481Timestamp.prototype.getHighBits = function() {
1490 return this.high_;
150};
151
152/**
153 * Return the low 32-bits value.
154 *
155 * @return {Number} the low 32-bits as a signed value.
156 * @api public
157 */
1581Timestamp.prototype.getLowBits = function() {
1590 return this.low_;
160};
161
162/**
163 * Return the low unsigned 32-bits value.
164 *
165 * @return {Number} the low 32-bits as an unsigned value.
166 * @api public
167 */
1681Timestamp.prototype.getLowBitsUnsigned = function() {
1690 return (this.low_ >= 0) ?
170 this.low_ : Timestamp.TWO_PWR_32_DBL_ + this.low_;
171};
172
173/**
174 * Returns the number of bits needed to represent the absolute value of this Timestamp.
175 *
176 * @return {Number} Returns the number of bits needed to represent the absolute value of this Timestamp.
177 * @api public
178 */
1791Timestamp.prototype.getNumBitsAbs = function() {
1800 if (this.isNegative()) {
1810 if (this.equals(Timestamp.MIN_VALUE)) {
1820 return 64;
183 } else {
1840 return this.negate().getNumBitsAbs();
185 }
186 } else {
1870 var val = this.high_ != 0 ? this.high_ : this.low_;
1880 for (var bit = 31; bit > 0; bit--) {
1890 if ((val & (1 << bit)) != 0) {
1900 break;
191 }
192 }
1930 return this.high_ != 0 ? bit + 33 : bit + 1;
194 }
195};
196
197/**
198 * Return whether this value is zero.
199 *
200 * @return {Boolean} whether this value is zero.
201 * @api public
202 */
2031Timestamp.prototype.isZero = function() {
2040 return this.high_ == 0 && this.low_ == 0;
205};
206
207/**
208 * Return whether this value is negative.
209 *
210 * @return {Boolean} whether this value is negative.
211 * @api public
212 */
2131Timestamp.prototype.isNegative = function() {
2140 return this.high_ < 0;
215};
216
217/**
218 * Return whether this value is odd.
219 *
220 * @return {Boolean} whether this value is odd.
221 * @api public
222 */
2231Timestamp.prototype.isOdd = function() {
2240 return (this.low_ & 1) == 1;
225};
226
227/**
228 * Return whether this Timestamp equals the other
229 *
230 * @param {Timestamp} other Timestamp to compare against.
231 * @return {Boolean} whether this Timestamp equals the other
232 * @api public
233 */
2341Timestamp.prototype.equals = function(other) {
2350 return (this.high_ == other.high_) && (this.low_ == other.low_);
236};
237
238/**
239 * Return whether this Timestamp does not equal the other.
240 *
241 * @param {Timestamp} other Timestamp to compare against.
242 * @return {Boolean} whether this Timestamp does not equal the other.
243 * @api public
244 */
2451Timestamp.prototype.notEquals = function(other) {
2460 return (this.high_ != other.high_) || (this.low_ != other.low_);
247};
248
249/**
250 * Return whether this Timestamp is less than the other.
251 *
252 * @param {Timestamp} other Timestamp to compare against.
253 * @return {Boolean} whether this Timestamp is less than the other.
254 * @api public
255 */
2561Timestamp.prototype.lessThan = function(other) {
2570 return this.compare(other) < 0;
258};
259
260/**
261 * Return whether this Timestamp is less than or equal to the other.
262 *
263 * @param {Timestamp} other Timestamp to compare against.
264 * @return {Boolean} whether this Timestamp is less than or equal to the other.
265 * @api public
266 */
2671Timestamp.prototype.lessThanOrEqual = function(other) {
2680 return this.compare(other) <= 0;
269};
270
271/**
272 * Return whether this Timestamp is greater than the other.
273 *
274 * @param {Timestamp} other Timestamp to compare against.
275 * @return {Boolean} whether this Timestamp is greater than the other.
276 * @api public
277 */
2781Timestamp.prototype.greaterThan = function(other) {
2790 return this.compare(other) > 0;
280};
281
282/**
283 * Return whether this Timestamp is greater than or equal to the other.
284 *
285 * @param {Timestamp} other Timestamp to compare against.
286 * @return {Boolean} whether this Timestamp is greater than or equal to the other.
287 * @api public
288 */
2891Timestamp.prototype.greaterThanOrEqual = function(other) {
2900 return this.compare(other) >= 0;
291};
292
293/**
294 * Compares this Timestamp with the given one.
295 *
296 * @param {Timestamp} other Timestamp to compare against.
297 * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater.
298 * @api public
299 */
3001Timestamp.prototype.compare = function(other) {
3010 if (this.equals(other)) {
3020 return 0;
303 }
304
3050 var thisNeg = this.isNegative();
3060 var otherNeg = other.isNegative();
3070 if (thisNeg && !otherNeg) {
3080 return -1;
309 }
3100 if (!thisNeg && otherNeg) {
3110 return 1;
312 }
313
314 // at this point, the signs are the same, so subtraction will not overflow
3150 if (this.subtract(other).isNegative()) {
3160 return -1;
317 } else {
3180 return 1;
319 }
320};
321
322/**
323 * The negation of this value.
324 *
325 * @return {Timestamp} the negation of this value.
326 * @api public
327 */
3281Timestamp.prototype.negate = function() {
3290 if (this.equals(Timestamp.MIN_VALUE)) {
3300 return Timestamp.MIN_VALUE;
331 } else {
3320 return this.not().add(Timestamp.ONE);
333 }
334};
335
336/**
337 * Returns the sum of this and the given Timestamp.
338 *
339 * @param {Timestamp} other Timestamp to add to this one.
340 * @return {Timestamp} the sum of this and the given Timestamp.
341 * @api public
342 */
3431Timestamp.prototype.add = function(other) {
344 // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
345
3460 var a48 = this.high_ >>> 16;
3470 var a32 = this.high_ & 0xFFFF;
3480 var a16 = this.low_ >>> 16;
3490 var a00 = this.low_ & 0xFFFF;
350
3510 var b48 = other.high_ >>> 16;
3520 var b32 = other.high_ & 0xFFFF;
3530 var b16 = other.low_ >>> 16;
3540 var b00 = other.low_ & 0xFFFF;
355
3560 var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
3570 c00 += a00 + b00;
3580 c16 += c00 >>> 16;
3590 c00 &= 0xFFFF;
3600 c16 += a16 + b16;
3610 c32 += c16 >>> 16;
3620 c16 &= 0xFFFF;
3630 c32 += a32 + b32;
3640 c48 += c32 >>> 16;
3650 c32 &= 0xFFFF;
3660 c48 += a48 + b48;
3670 c48 &= 0xFFFF;
3680 return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
369};
370
371/**
372 * Returns the difference of this and the given Timestamp.
373 *
374 * @param {Timestamp} other Timestamp to subtract from this.
375 * @return {Timestamp} the difference of this and the given Timestamp.
376 * @api public
377 */
3781Timestamp.prototype.subtract = function(other) {
3790 return this.add(other.negate());
380};
381
382/**
383 * Returns the product of this and the given Timestamp.
384 *
385 * @param {Timestamp} other Timestamp to multiply with this.
386 * @return {Timestamp} the product of this and the other.
387 * @api public
388 */
3891Timestamp.prototype.multiply = function(other) {
3900 if (this.isZero()) {
3910 return Timestamp.ZERO;
3920 } else if (other.isZero()) {
3930 return Timestamp.ZERO;
394 }
395
3960 if (this.equals(Timestamp.MIN_VALUE)) {
3970 return other.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO;
3980 } else if (other.equals(Timestamp.MIN_VALUE)) {
3990 return this.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO;
400 }
401
4020 if (this.isNegative()) {
4030 if (other.isNegative()) {
4040 return this.negate().multiply(other.negate());
405 } else {
4060 return this.negate().multiply(other).negate();
407 }
4080 } else if (other.isNegative()) {
4090 return this.multiply(other.negate()).negate();
410 }
411
412 // If both Timestamps are small, use float multiplication
4130 if (this.lessThan(Timestamp.TWO_PWR_24_) &&
414 other.lessThan(Timestamp.TWO_PWR_24_)) {
4150 return Timestamp.fromNumber(this.toNumber() * other.toNumber());
416 }
417
418 // Divide each Timestamp into 4 chunks of 16 bits, and then add up 4x4 products.
419 // We can skip products that would overflow.
420
4210 var a48 = this.high_ >>> 16;
4220 var a32 = this.high_ & 0xFFFF;
4230 var a16 = this.low_ >>> 16;
4240 var a00 = this.low_ & 0xFFFF;
425
4260 var b48 = other.high_ >>> 16;
4270 var b32 = other.high_ & 0xFFFF;
4280 var b16 = other.low_ >>> 16;
4290 var b00 = other.low_ & 0xFFFF;
430
4310 var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
4320 c00 += a00 * b00;
4330 c16 += c00 >>> 16;
4340 c00 &= 0xFFFF;
4350 c16 += a16 * b00;
4360 c32 += c16 >>> 16;
4370 c16 &= 0xFFFF;
4380 c16 += a00 * b16;
4390 c32 += c16 >>> 16;
4400 c16 &= 0xFFFF;
4410 c32 += a32 * b00;
4420 c48 += c32 >>> 16;
4430 c32 &= 0xFFFF;
4440 c32 += a16 * b16;
4450 c48 += c32 >>> 16;
4460 c32 &= 0xFFFF;
4470 c32 += a00 * b32;
4480 c48 += c32 >>> 16;
4490 c32 &= 0xFFFF;
4500 c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
4510 c48 &= 0xFFFF;
4520 return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
453};
454
455/**
456 * Returns this Timestamp divided by the given one.
457 *
458 * @param {Timestamp} other Timestamp by which to divide.
459 * @return {Timestamp} this Timestamp divided by the given one.
460 * @api public
461 */
4621Timestamp.prototype.div = function(other) {
4630 if (other.isZero()) {
4640 throw Error('division by zero');
4650 } else if (this.isZero()) {
4660 return Timestamp.ZERO;
467 }
468
4690 if (this.equals(Timestamp.MIN_VALUE)) {
4700 if (other.equals(Timestamp.ONE) ||
471 other.equals(Timestamp.NEG_ONE)) {
4720 return Timestamp.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
4730 } else if (other.equals(Timestamp.MIN_VALUE)) {
4740 return Timestamp.ONE;
475 } else {
476 // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
4770 var halfThis = this.shiftRight(1);
4780 var approx = halfThis.div(other).shiftLeft(1);
4790 if (approx.equals(Timestamp.ZERO)) {
4800 return other.isNegative() ? Timestamp.ONE : Timestamp.NEG_ONE;
481 } else {
4820 var rem = this.subtract(other.multiply(approx));
4830 var result = approx.add(rem.div(other));
4840 return result;
485 }
486 }
4870 } else if (other.equals(Timestamp.MIN_VALUE)) {
4880 return Timestamp.ZERO;
489 }
490
4910 if (this.isNegative()) {
4920 if (other.isNegative()) {
4930 return this.negate().div(other.negate());
494 } else {
4950 return this.negate().div(other).negate();
496 }
4970 } else if (other.isNegative()) {
4980 return this.div(other.negate()).negate();
499 }
500
501 // Repeat the following until the remainder is less than other: find a
502 // floating-point that approximates remainder / other *from below*, add this
503 // into the result, and subtract it from the remainder. It is critical that
504 // the approximate value is less than or equal to the real value so that the
505 // remainder never becomes negative.
5060 var res = Timestamp.ZERO;
5070 var rem = this;
5080 while (rem.greaterThanOrEqual(other)) {
509 // Approximate the result of division. This may be a little greater or
510 // smaller than the actual value.
5110 var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
512
513 // We will tweak the approximate result by changing it in the 48-th digit or
514 // the smallest non-fractional digit, whichever is larger.
5150 var log2 = Math.ceil(Math.log(approx) / Math.LN2);
5160 var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
517
518 // Decrease the approximation until it is smaller than the remainder. Note
519 // that if it is too large, the product overflows and is negative.
5200 var approxRes = Timestamp.fromNumber(approx);
5210 var approxRem = approxRes.multiply(other);
5220 while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
5230 approx -= delta;
5240 approxRes = Timestamp.fromNumber(approx);
5250 approxRem = approxRes.multiply(other);
526 }
527
528 // We know the answer can't be zero... and actually, zero would cause
529 // infinite recursion since we would make no progress.
5300 if (approxRes.isZero()) {
5310 approxRes = Timestamp.ONE;
532 }
533
5340 res = res.add(approxRes);
5350 rem = rem.subtract(approxRem);
536 }
5370 return res;
538};
539
540/**
541 * Returns this Timestamp modulo the given one.
542 *
543 * @param {Timestamp} other Timestamp by which to mod.
544 * @return {Timestamp} this Timestamp modulo the given one.
545 * @api public
546 */
5471Timestamp.prototype.modulo = function(other) {
5480 return this.subtract(this.div(other).multiply(other));
549};
550
551/**
552 * The bitwise-NOT of this value.
553 *
554 * @return {Timestamp} the bitwise-NOT of this value.
555 * @api public
556 */
5571Timestamp.prototype.not = function() {
5580 return Timestamp.fromBits(~this.low_, ~this.high_);
559};
560
561/**
562 * Returns the bitwise-AND of this Timestamp and the given one.
563 *
564 * @param {Timestamp} other the Timestamp with which to AND.
565 * @return {Timestamp} the bitwise-AND of this and the other.
566 * @api public
567 */
5681Timestamp.prototype.and = function(other) {
5690 return Timestamp.fromBits(this.low_ & other.low_, this.high_ & other.high_);
570};
571
572/**
573 * Returns the bitwise-OR of this Timestamp and the given one.
574 *
575 * @param {Timestamp} other the Timestamp with which to OR.
576 * @return {Timestamp} the bitwise-OR of this and the other.
577 * @api public
578 */
5791Timestamp.prototype.or = function(other) {
5800 return Timestamp.fromBits(this.low_ | other.low_, this.high_ | other.high_);
581};
582
583/**
584 * Returns the bitwise-XOR of this Timestamp and the given one.
585 *
586 * @param {Timestamp} other the Timestamp with which to XOR.
587 * @return {Timestamp} the bitwise-XOR of this and the other.
588 * @api public
589 */
5901Timestamp.prototype.xor = function(other) {
5910 return Timestamp.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_);
592};
593
594/**
595 * Returns this Timestamp with bits shifted to the left by the given amount.
596 *
597 * @param {Number} numBits the number of bits by which to shift.
598 * @return {Timestamp} this shifted to the left by the given amount.
599 * @api public
600 */
6011Timestamp.prototype.shiftLeft = function(numBits) {
6020 numBits &= 63;
6030 if (numBits == 0) {
6040 return this;
605 } else {
6060 var low = this.low_;
6070 if (numBits < 32) {
6080 var high = this.high_;
6090 return Timestamp.fromBits(
610 low << numBits,
611 (high << numBits) | (low >>> (32 - numBits)));
612 } else {
6130 return Timestamp.fromBits(0, low << (numBits - 32));
614 }
615 }
616};
617
618/**
619 * Returns this Timestamp with bits shifted to the right by the given amount.
620 *
621 * @param {Number} numBits the number of bits by which to shift.
622 * @return {Timestamp} this shifted to the right by the given amount.
623 * @api public
624 */
6251Timestamp.prototype.shiftRight = function(numBits) {
6260 numBits &= 63;
6270 if (numBits == 0) {
6280 return this;
629 } else {
6300 var high = this.high_;
6310 if (numBits < 32) {
6320 var low = this.low_;
6330 return Timestamp.fromBits(
634 (low >>> numBits) | (high << (32 - numBits)),
635 high >> numBits);
636 } else {
6370 return Timestamp.fromBits(
638 high >> (numBits - 32),
639 high >= 0 ? 0 : -1);
640 }
641 }
642};
643
644/**
645 * Returns this Timestamp with bits shifted to the right by the given amount, with the new top bits matching the current sign bit.
646 *
647 * @param {Number} numBits the number of bits by which to shift.
648 * @return {Timestamp} this shifted to the right by the given amount, with zeros placed into the new leading bits.
649 * @api public
650 */
6511Timestamp.prototype.shiftRightUnsigned = function(numBits) {
6520 numBits &= 63;
6530 if (numBits == 0) {
6540 return this;
655 } else {
6560 var high = this.high_;
6570 if (numBits < 32) {
6580 var low = this.low_;
6590 return Timestamp.fromBits(
660 (low >>> numBits) | (high << (32 - numBits)),
661 high >>> numBits);
6620 } else if (numBits == 32) {
6630 return Timestamp.fromBits(high, 0);
664 } else {
6650 return Timestamp.fromBits(high >>> (numBits - 32), 0);
666 }
667 }
668};
669
670/**
671 * Returns a Timestamp representing the given (32-bit) integer value.
672 *
673 * @param {Number} value the 32-bit integer in question.
674 * @return {Timestamp} the corresponding Timestamp value.
675 * @api public
676 */
6771Timestamp.fromInt = function(value) {
6784 if (-128 <= value && value < 128) {
6793 var cachedObj = Timestamp.INT_CACHE_[value];
6803 if (cachedObj) {
6810 return cachedObj;
682 }
683 }
684
6854 var obj = new Timestamp(value | 0, value < 0 ? -1 : 0);
6864 if (-128 <= value && value < 128) {
6873 Timestamp.INT_CACHE_[value] = obj;
688 }
6894 return obj;
690};
691
692/**
693 * Returns a Timestamp representing the given value, provided that it is a finite number. Otherwise, zero is returned.
694 *
695 * @param {Number} value the number in question.
696 * @return {Timestamp} the corresponding Timestamp value.
697 * @api public
698 */
6991Timestamp.fromNumber = function(value) {
7000 if (isNaN(value) || !isFinite(value)) {
7010 return Timestamp.ZERO;
7020 } else if (value <= -Timestamp.TWO_PWR_63_DBL_) {
7030 return Timestamp.MIN_VALUE;
7040 } else if (value + 1 >= Timestamp.TWO_PWR_63_DBL_) {
7050 return Timestamp.MAX_VALUE;
7060 } else if (value < 0) {
7070 return Timestamp.fromNumber(-value).negate();
708 } else {
7090 return new Timestamp(
710 (value % Timestamp.TWO_PWR_32_DBL_) | 0,
711 (value / Timestamp.TWO_PWR_32_DBL_) | 0);
712 }
713};
714
715/**
716 * Returns a Timestamp representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits.
717 *
718 * @param {Number} lowBits the low 32-bits.
719 * @param {Number} highBits the high 32-bits.
720 * @return {Timestamp} the corresponding Timestamp value.
721 * @api public
722 */
7231Timestamp.fromBits = function(lowBits, highBits) {
7242 return new Timestamp(lowBits, highBits);
725};
726
727/**
728 * Returns a Timestamp representation of the given string, written using the given radix.
729 *
730 * @param {String} str the textual representation of the Timestamp.
731 * @param {Number} opt_radix the radix in which the text is written.
732 * @return {Timestamp} the corresponding Timestamp value.
733 * @api public
734 */
7351Timestamp.fromString = function(str, opt_radix) {
7360 if (str.length == 0) {
7370 throw Error('number format error: empty string');
738 }
739
7400 var radix = opt_radix || 10;
7410 if (radix < 2 || 36 < radix) {
7420 throw Error('radix out of range: ' + radix);
743 }
744
7450 if (str.charAt(0) == '-') {
7460 return Timestamp.fromString(str.substring(1), radix).negate();
7470 } else if (str.indexOf('-') >= 0) {
7480 throw Error('number format error: interior "-" character: ' + str);
749 }
750
751 // Do several (8) digits each time through the loop, so as to
752 // minimize the calls to the very expensive emulated div.
7530 var radixToPower = Timestamp.fromNumber(Math.pow(radix, 8));
754
7550 var result = Timestamp.ZERO;
7560 for (var i = 0; i < str.length; i += 8) {
7570 var size = Math.min(8, str.length - i);
7580 var value = parseInt(str.substring(i, i + size), radix);
7590 if (size < 8) {
7600 var power = Timestamp.fromNumber(Math.pow(radix, size));
7610 result = result.multiply(power).add(Timestamp.fromNumber(value));
762 } else {
7630 result = result.multiply(radixToPower);
7640 result = result.add(Timestamp.fromNumber(value));
765 }
766 }
7670 return result;
768};
769
770// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
771// from* methods on which they depend.
772
773
774/**
775 * A cache of the Timestamp representations of small integer values.
776 * @type {Object}
777 * @api private
778 */
7791Timestamp.INT_CACHE_ = {};
780
781// NOTE: the compiler should inline these constant values below and then remove
782// these variables, so there should be no runtime penalty for these.
783
784/**
785 * Number used repeated below in calculations. This must appear before the
786 * first call to any from* function below.
787 * @type {number}
788 * @api private
789 */
7901Timestamp.TWO_PWR_16_DBL_ = 1 << 16;
791
792/**
793 * @type {number}
794 * @api private
795 */
7961Timestamp.TWO_PWR_24_DBL_ = 1 << 24;
797
798/**
799 * @type {number}
800 * @api private
801 */
8021Timestamp.TWO_PWR_32_DBL_ = Timestamp.TWO_PWR_16_DBL_ * Timestamp.TWO_PWR_16_DBL_;
803
804/**
805 * @type {number}
806 * @api private
807 */
8081Timestamp.TWO_PWR_31_DBL_ = Timestamp.TWO_PWR_32_DBL_ / 2;
809
810/**
811 * @type {number}
812 * @api private
813 */
8141Timestamp.TWO_PWR_48_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_16_DBL_;
815
816/**
817 * @type {number}
818 * @api private
819 */
8201Timestamp.TWO_PWR_64_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_32_DBL_;
821
822/**
823 * @type {number}
824 * @api private
825 */
8261Timestamp.TWO_PWR_63_DBL_ = Timestamp.TWO_PWR_64_DBL_ / 2;
827
828/** @type {Timestamp} */
8291Timestamp.ZERO = Timestamp.fromInt(0);
830
831/** @type {Timestamp} */
8321Timestamp.ONE = Timestamp.fromInt(1);
833
834/** @type {Timestamp} */
8351Timestamp.NEG_ONE = Timestamp.fromInt(-1);
836
837/** @type {Timestamp} */
8381Timestamp.MAX_VALUE =
839 Timestamp.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0);
840
841/** @type {Timestamp} */
8421Timestamp.MIN_VALUE = Timestamp.fromBits(0, 0x80000000 | 0);
843
844/**
845 * @type {Timestamp}
846 * @api private
847 */
8481Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24);
849
850/**
851 * Expose.
852 */
8531exports.Timestamp = Timestamp;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js

13%
132
18
114
LineHitsSource
11var format = require('util').format;
2
31var MongoAuthProcess = function(host, port, service_name) {
4 // Check what system we are on
50 if(process.platform == 'win32') {
60 this._processor = new Win32MongoProcessor(host, port, service_name);
7 } else {
80 this._processor = new UnixMongoProcessor(host, port, service_name);
9 }
10}
11
121MongoAuthProcess.prototype.init = function(username, password, callback) {
130 this._processor.init(username, password, callback);
14}
15
161MongoAuthProcess.prototype.transition = function(payload, callback) {
170 this._processor.transition(payload, callback);
18}
19
20/*******************************************************************
21 *
22 * Win32 SSIP Processor for MongoDB
23 *
24 *******************************************************************/
251var Win32MongoProcessor = function(host, port, service_name) {
260 this.host = host;
270 this.port = port
28 // SSIP classes
290 this.ssip = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/../kerberos").SSIP;
30 // Set up first transition
310 this._transition = Win32MongoProcessor.first_transition(this);
32 // Set up service name
330 service_name = service_name || "mongodb";
34 // Set up target
350 this.target = format("%s/%s", service_name, host);
36 // Number of retries
370 this.retries = 10;
38}
39
401Win32MongoProcessor.prototype.init = function(username, password, callback) {
410 var self = this;
42 // Save the values used later
430 this.username = username;
440 this.password = password;
45 // Aquire credentials
460 this.ssip.SecurityCredentials.aquire_kerberos(username, password, function(err, security_credentials) {
470 if(err) return callback(err);
48 // Save credentials
490 self.security_credentials = security_credentials;
50 // Callback with success
510 callback(null);
52 });
53}
54
551Win32MongoProcessor.prototype.transition = function(payload, callback) {
560 if(this._transition == null) return callback(new Error("Transition finished"));
570 this._transition(payload, callback);
58}
59
601Win32MongoProcessor.first_transition = function(self) {
610 return function(payload, callback) {
620 self.ssip.SecurityContext.initialize(
63 self.security_credentials,
64 self.target,
65 payload, function(err, security_context) {
660 if(err) return callback(err);
67
68 // If no context try again until we have no more retries
690 if(!security_context.hasContext) {
700 if(self.retries == 0) return callback(new Error("Failed to initialize security context"));
71 // Update the number of retries
720 self.retries = self.retries - 1;
73 // Set next transition
740 return self.transition(payload, callback);
75 }
76
77 // Set next transition
780 self._transition = Win32MongoProcessor.second_transition(self);
790 self.security_context = security_context;
80 // Return the payload
810 callback(null, security_context.payload);
82 });
83 }
84}
85
861Win32MongoProcessor.second_transition = function(self) {
870 return function(payload, callback) {
88 // Perform a step
890 self.security_context.initialize(self.target, payload, function(err, security_context) {
900 if(err) return callback(err);
91
92 // If no context try again until we have no more retries
930 if(!security_context.hasContext) {
940 if(self.retries == 0) return callback(new Error("Failed to initialize security context"));
95 // Update the number of retries
960 self.retries = self.retries - 1;
97 // Set next transition
980 self._transition = Win32MongoProcessor.first_transition(self);
99 // Retry
1000 return self.transition(payload, callback);
101 }
102
103 // Set next transition
1040 self._transition = Win32MongoProcessor.third_transition(self);
105 // Return the payload
1060 callback(null, security_context.payload);
107 });
108 }
109}
110
1111Win32MongoProcessor.third_transition = function(self) {
1120 return function(payload, callback) {
1130 var messageLength = 0;
114 // Get the raw bytes
1150 var encryptedBytes = new Buffer(payload, 'base64');
1160 var encryptedMessage = new Buffer(messageLength);
117 // Copy first byte
1180 encryptedBytes.copy(encryptedMessage, 0, 0, messageLength);
119 // Set up trailer
1200 var securityTrailerLength = encryptedBytes.length - messageLength;
1210 var securityTrailer = new Buffer(securityTrailerLength);
122 // Copy the bytes
1230 encryptedBytes.copy(securityTrailer, 0, messageLength, securityTrailerLength);
124
125 // Types used
1260 var SecurityBuffer = self.ssip.SecurityBuffer;
1270 var SecurityBufferDescriptor = self.ssip.SecurityBufferDescriptor;
128
129 // Set up security buffers
1300 var buffers = [
131 new SecurityBuffer(SecurityBuffer.DATA, encryptedBytes)
132 , new SecurityBuffer(SecurityBuffer.STREAM, securityTrailer)
133 ];
134
135 // Set up the descriptor
1360 var descriptor = new SecurityBufferDescriptor(buffers);
137
138 // Decrypt the data
1390 self.security_context.decryptMessage(descriptor, function(err, security_context) {
1400 if(err) return callback(err);
141
1420 var length = 4;
1430 if(self.username != null) {
1440 length += self.username.length;
145 }
146
1470 var bytesReceivedFromServer = new Buffer(length);
1480 bytesReceivedFromServer[0] = 0x01; // NO_PROTECTION
1490 bytesReceivedFromServer[1] = 0x00; // NO_PROTECTION
1500 bytesReceivedFromServer[2] = 0x00; // NO_PROTECTION
1510 bytesReceivedFromServer[3] = 0x00; // NO_PROTECTION
152
1530 if(self.username != null) {
1540 var authorization_id_bytes = new Buffer(self.username, 'utf8');
1550 authorization_id_bytes.copy(bytesReceivedFromServer, 4, 0);
156 }
157
1580 self.security_context.queryContextAttributes(0x00, function(err, sizes) {
1590 if(err) return callback(err);
160
1610 var buffers = [
162 new SecurityBuffer(SecurityBuffer.TOKEN, new Buffer(sizes.securityTrailer))
163 , new SecurityBuffer(SecurityBuffer.DATA, bytesReceivedFromServer)
164 , new SecurityBuffer(SecurityBuffer.PADDING, new Buffer(sizes.blockSize))
165 ]
166
1670 var descriptor = new SecurityBufferDescriptor(buffers);
168
1690 self.security_context.encryptMessage(descriptor, 0x80000001, function(err, security_context) {
1700 if(err) return callback(err);
1710 callback(null, security_context.payload);
172 });
173 });
174 });
175 }
176}
177
178/*******************************************************************
179 *
180 * UNIX MIT Kerberos processor
181 *
182 *******************************************************************/
1831var UnixMongoProcessor = function(host, port, service_name) {
1840 this.host = host;
1850 this.port = port
186 // SSIP classes
1870 this.Kerberos = require("/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/../kerberos").Kerberos;
1880 this.kerberos = new this.Kerberos();
1890 service_name = service_name || "mongodb";
190 // Set up first transition
1910 this._transition = UnixMongoProcessor.first_transition(this);
192 // Set up target
1930 this.target = format("%s@%s", service_name, host);
194 // Number of retries
1950 this.retries = 10;
196}
197
1981UnixMongoProcessor.prototype.init = function(username, password, callback) {
1990 var self = this;
2000 this.username = username;
2010 this.password = password;
202 // Call client initiate
2030 this.kerberos.authGSSClientInit(
204 self.target
205 , this.Kerberos.GSS_C_MUTUAL_FLAG, function(err, context) {
2060 self.context = context;
207 // Return the context
2080 callback(null, context);
209 });
210}
211
2121UnixMongoProcessor.prototype.transition = function(payload, callback) {
2130 if(this._transition == null) return callback(new Error("Transition finished"));
2140 this._transition(payload, callback);
215}
216
2171UnixMongoProcessor.first_transition = function(self) {
2180 return function(payload, callback) {
2190 self.kerberos.authGSSClientStep(self.context, '', function(err, result) {
2200 if(err) return callback(err);
221 // Set up the next step
2220 self._transition = UnixMongoProcessor.second_transition(self);
223 // Return the payload
2240 callback(null, self.context.response);
225 })
226 }
227}
228
2291UnixMongoProcessor.second_transition = function(self) {
2300 return function(payload, callback) {
2310 self.kerberos.authGSSClientStep(self.context, payload, function(err, result) {
2320 if(err && self.retries == 0) return callback(err);
233 // Attempt to re-establish a context
2340 if(err) {
235 // Adjust the number of retries
2360 self.retries = self.retries - 1;
237 // Call same step again
2380 return self.transition(payload, callback);
239 }
240
241 // Set up the next step
2420 self._transition = UnixMongoProcessor.third_transition(self);
243 // Return the payload
2440 callback(null, self.context.response || '');
245 });
246 }
247}
248
2491UnixMongoProcessor.third_transition = function(self) {
2500 return function(payload, callback) {
251 // GSS Client Unwrap
2520 self.kerberos.authGSSClientUnwrap(self.context, payload, function(err, result) {
2530 if(err) return callback(err, false);
254
255 // Wrap the response
2560 self.kerberos.authGSSClientWrap(self.context, self.context.response, self.username, function(err, result) {
2570 if(err) return callback(err, false);
258 // Set up the next step
2590 self._transition = UnixMongoProcessor.fourth_transition(self);
260 // Return the payload
2610 callback(null, self.context.response);
262 });
263 });
264 }
265}
266
2671UnixMongoProcessor.fourth_transition = function(self) {
2680 return function(payload, callback) {
269 // Clean up context
2700 self.kerberos.authGSSClientClean(self.context, function(err, result) {
2710 if(err) return callback(err, false);
272 // Set the transition to null
2730 self._transition = null;
274 // Callback with valid authentication
2750 callback(null, true);
276 });
277 }
278}
279
280// Set the process
2811exports.MongoAuthProcess = MongoAuthProcess;

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js

53%
47
25
22
LineHitsSource
11var kerberos = require('../build/Release/kerberos')
2 , KerberosNative = kerberos.Kerberos;
3
41var Kerberos = function() {
50 this._native_kerberos = new KerberosNative();
6}
7
81Kerberos.prototype.authGSSClientInit = function(uri, flags, callback) {
90 return this._native_kerberos.authGSSClientInit(uri, flags, callback);
10}
11
121Kerberos.prototype.authGSSClientStep = function(context, challenge, callback) {
130 if(typeof challenge == 'function') {
140 callback = challenge;
150 challenge = '';
16 }
17
180 return this._native_kerberos.authGSSClientStep(context, challenge, callback);
19}
20
211Kerberos.prototype.authGSSClientUnwrap = function(context, challenge, callback) {
220 if(typeof challenge == 'function') {
230 callback = challenge;
240 challenge = '';
25 }
26
270 return this._native_kerberos.authGSSClientUnwrap(context, challenge, callback);
28}
29
301Kerberos.prototype.authGSSClientWrap = function(context, challenge, user_name, callback) {
310 if(typeof user_name == 'function') {
320 callback = user_name;
330 user_name = '';
34 }
35
360 return this._native_kerberos.authGSSClientWrap(context, challenge, user_name, callback);
37}
38
391Kerberos.prototype.authGSSClientClean = function(context, callback) {
400 return this._native_kerberos.authGSSClientClean(context, callback);
41}
42
431Kerberos.prototype.acquireAlternateCredentials = function(user_name, password, domain) {
440 return this._native_kerberos.acquireAlternateCredentials(user_name, password, domain);
45}
46
471Kerberos.prototype.prepareOutboundPackage = function(principal, inputdata) {
480 return this._native_kerberos.prepareOutboundPackage(principal, inputdata);
49}
50
511Kerberos.prototype.decryptMessage = function(challenge) {
520 return this._native_kerberos.decryptMessage(challenge);
53}
54
551Kerberos.prototype.encryptMessage = function(challenge) {
560 return this._native_kerberos.encryptMessage(challenge);
57}
58
591Kerberos.prototype.queryContextAttribute = function(attribute) {
600 if(typeof attribute != 'number' && attribute != 0x00) throw new Error("Attribute not supported");
610 return this._native_kerberos.queryContextAttribute(attribute);
62}
63
64// Some useful result codes
651Kerberos.AUTH_GSS_CONTINUE = 0;
661Kerberos.AUTH_GSS_COMPLETE = 1;
67
68// Some useful gss flags
691Kerberos.GSS_C_DELEG_FLAG = 1;
701Kerberos.GSS_C_MUTUAL_FLAG = 2;
711Kerberos.GSS_C_REPLAY_FLAG = 4;
721Kerberos.GSS_C_SEQUENCE_FLAG = 8;
731Kerberos.GSS_C_CONF_FLAG = 16;
741Kerberos.GSS_C_INTEG_FLAG = 32;
751Kerberos.GSS_C_ANON_FLAG = 64;
761Kerberos.GSS_C_PROT_READY_FLAG = 128;
771Kerberos.GSS_C_TRANS_FLAG = 256;
78
79// Export Kerberos class
801exports.Kerberos = Kerberos;
81
82// If we have SSPI (windows)
831if(kerberos.SecurityCredentials) {
84 // Put all SSPI classes in it's own namespace
850 exports.SSIP = {
86 SecurityCredentials: require('./win32/wrappers/security_credentials').SecurityCredentials
87 , SecurityContext: require('./win32/wrappers/security_context').SecurityContext
88 , SecurityBuffer: require('./win32/wrappers/security_buffer').SecurityBuffer
89 , SecurityBufferDescriptor: require('./win32/wrappers/security_buffer_descriptor').SecurityBufferDescriptor
90 }
91}
92

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mpath/lib/index.js

4%
62
3
59
LineHitsSource
1
2/**
3 * Returns the value of object `o` at the given `path`.
4 *
5 * ####Example:
6 *
7 * var obj = {
8 * comments: [
9 * { title: 'exciting!', _doc: { title: 'great!' }}
10 * , { title: 'number dos' }
11 * ]
12 * }
13 *
14 * mpath.get('comments.0.title', o) // 'exciting!'
15 * mpath.get('comments.0.title', o, '_doc') // 'great!'
16 * mpath.get('comments.title', o) // ['exciting!', 'number dos']
17 *
18 * // summary
19 * mpath.get(path, o)
20 * mpath.get(path, o, special)
21 * mpath.get(path, o, map)
22 * mpath.get(path, o, special, map)
23 *
24 * @param {String} path
25 * @param {Object} o
26 * @param {String} [special] When this property name is present on any object in the path, walking will continue on the value of this property.
27 * @param {Function} [map] Optional function which receives each individual found value. The value returned from `map` is used in the original values place.
28 */
29
301exports.get = function (path, o, special, map) {
310 if ('function' == typeof special) {
320 map = special;
330 special = undefined;
34 }
35
360 map || (map = K);
37
380 var parts = 'string' == typeof path
39 ? path.split('.')
40 : path
41
420 if (!Array.isArray(parts)) {
430 throw new TypeError('Invalid `path`. Must be either string or array');
44 }
45
460 var obj = o
47 , part;
48
490 for (var i = 0; i < parts.length; ++i) {
500 part = parts[i];
51
520 if (Array.isArray(obj) && !/^\d+$/.test(part)) {
53 // reading a property from the array items
540 var paths = parts.slice(i);
55
560 return obj.map(function (item) {
570 return item
58 ? exports.get(paths, item, special, map)
59 : map(undefined);
60 });
61 }
62
630 obj = special && obj[special]
64 ? obj[special][part]
65 : obj[part];
66
670 if (!obj) return map(obj);
68 }
69
700 return map(obj);
71}
72
73/**
74 * Sets the `val` at the given `path` of object `o`.
75 *
76 * @param {String} path
77 * @param {Anything} val
78 * @param {Object} o
79 * @param {String} [special] When this property name is present on any object in the path, walking will continue on the value of this property.
80 * @param {Function} [map] Optional function which is passed each individual value before setting it. The value returned from `map` is used in the original values place.
81
82 */
83
841exports.set = function (path, val, o, special, map, _copying) {
850 if ('function' == typeof special) {
860 map = special;
870 special = undefined;
88 }
89
900 map || (map = K);
91
920 var parts = 'string' == typeof path
93 ? path.split('.')
94 : path
95
960 if (!Array.isArray(parts)) {
970 throw new TypeError('Invalid `path`. Must be either string or array');
98 }
99
1000 if (null == o) return;
101
102 // the existance of $ in a path tells us if the user desires
103 // the copying of an array instead of setting each value of
104 // the array to the one by one to matching positions of the
105 // current array.
1060 var copy = _copying || /\$/.test(path)
107 , obj = o
108 , part
109
1100 for (var i = 0, len = parts.length - 1; i < len; ++i) {
1110 part = parts[i];
112
1130 if ('$' == part) {
1140 if (i == len - 1) {
1150 break;
116 } else {
1170 continue;
118 }
119 }
120
1210 if (Array.isArray(obj) && !/^\d+$/.test(part)) {
1220 var paths = parts.slice(i);
1230 if (!copy && Array.isArray(val)) {
1240 for (var j = 0; j < obj.length && j < val.length; ++j) {
125 // assignment of single values of array
1260 exports.set(paths, val[j], obj[j], special, map, copy);
127 }
128 } else {
1290 for (var j = 0; j < obj.length; ++j) {
130 // assignment of entire value
1310 exports.set(paths, val, obj[j], special, map, copy);
132 }
133 }
1340 return;
135 }
136
1370 obj = special && obj[special]
138 ? obj[special][part]
139 : obj[part];
140
1410 if (!obj) return;
142 }
143
144 // process the last property of the path
145
1460 part = parts[len];
147
148 // use the special property if exists
1490 if (special && obj[special]) {
1500 obj = obj[special];
151 }
152
153 // set the value on the last branch
1540 if (Array.isArray(obj) && !/^\d+$/.test(part)) {
1550 if (!copy && Array.isArray(val)) {
1560 for (var item, j = 0; j < obj.length && j < val.length; ++j) {
1570 item = obj[j];
1580 if (item) {
1590 if (item[special]) item = item[special];
1600 item[part] = map(val[j]);
161 }
162 }
163 } else {
1640 for (var j = 0; j < obj.length; ++j) {
1650 item = obj[j];
1660 if (item) {
1670 if (item[special]) item = item[special];
1680 item[part] = map(val);
169 }
170 }
171 }
172 } else {
1730 obj[part] = map(val);
174 }
175}
176
177/*!
178 * Returns the value passed to it.
179 */
180
1811function K (v) {
1820 return v;
183}
184

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mpromise/lib/promise.js

18%
113
21
92
LineHitsSource
11'use strict';
2
3/*!
4 * Module dependencies.
5 */
6
71var slice = function (arr, start, end) {
80 return Array.prototype.slice.call(arr, start, end)
9};
101var EventEmitter = require('events').EventEmitter;
11
12/**
13 * Promise constructor.
14 *
15 * _NOTE: The success and failure event names can be overridden by setting `Promise.SUCCESS` and `Promise.FAILURE` respectively._
16 *
17 * @param {Function} back a function that accepts `fn(err, ...){}` as signature
18 * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
19 * @event `reject`: Emits when the promise is rejected (event name may be overridden)
20 * @event `fulfill`: Emits when the promise is fulfilled (event name may be overridden)
21 * @api public
22 */
23
241function Promise(back) {
250 EventEmitter.call(this);
26
270 this.emitted = {};
280 this.ended = false;
290 if ('function' == typeof back)
300 this.onResolve(back);
31}
32
33/*!
34 * event names
35 */
36
371Promise.SUCCESS = 'fulfill';
381Promise.FAILURE = 'reject';
39
40/*!
41 * Inherits from EventEmitter.
42 */
43
441Promise.prototype.__proto__ = EventEmitter.prototype;
45
46/**
47 * Adds `listener` to the `event`.
48 *
49 * If `event` is either the success or failure event and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event.
50 *
51 * @param {String} event
52 * @param {Function} callback
53 * @return {Promise} this
54 * @api public
55 */
56
571Promise.prototype.on = function (event, callback) {
580 if (this.emitted[event])
590 callback.apply(this, this.emitted[event]);
60 else
610 EventEmitter.prototype.on.call(this, event, callback);
62
630 return this;
64}
65
66/**
67 * Keeps track of emitted events to run them on `on`.
68 *
69 * @api private
70 */
71
721Promise.prototype.emit = function (event) {
73 // ensures a promise can't be fulfill() or reject() more than once
740 var success = this.constructor.SUCCESS;
750 var failure = this.constructor.FAILURE;
76
770 if (event == success || event == failure) {
780 if (this.emitted[success] || this.emitted[failure]) {
790 return this;
80 }
810 this.emitted[event] = slice(arguments, 1);
82 }
83
840 return EventEmitter.prototype.emit.apply(this, arguments);
85}
86
87/**
88 * Fulfills this promise with passed arguments.
89 *
90 * If this promise has already been fulfilled or rejected, no action is taken.
91 *
92 * @api public
93 */
94
951Promise.prototype.fulfill = function () {
960 var args = slice(arguments);
970 return this.emit.apply(this, [this.constructor.SUCCESS].concat(args));
98}
99
100/**
101 * Rejects this promise with `reason`.
102 *
103 * If this promise has already been fulfilled or rejected, no action is taken.
104 *
105 * @api public
106 * @param {Object|String} reason
107 * @return {Promise} this
108 */
109
1101Promise.prototype.reject = function (reason) {
1110 return this.emit(this.constructor.FAILURE, reason);
112}
113
114/**
115 * Resolves this promise to a rejected state if `err` is passed or
116 * fulfilled state if no `err` is passed.
117 *
118 * @param {Error} [err] error or null
119 * @param {Object} [val] value to fulfill the promise with
120 * @api public
121 */
122
1231Promise.prototype.resolve = function (err, val) {
1240 if (err) return this.reject(err);
1250 return this.fulfill(val);
126}
127
128/**
129 * Adds a listener to the SUCCESS event.
130 *
131 * @return {Promise} this
132 * @api public
133 */
134
1351Promise.prototype.onFulfill = function (fn) {
1360 if (!fn) return this;
1370 if ('function' != typeof fn) throw new TypeError("fn should be a function");
1380 return this.on(this.constructor.SUCCESS, fn);
139}
140
1411Promise.prototype.hasRejectListeners = function () {
1420 return this.listeners(this.constructor.FAILURE).length > 0;
143};
144/**
145 * Adds a listener to the FAILURE event.
146 *
147 * @return {Promise} this
148 * @api public
149 */
150
1511Promise.prototype.onReject = function (fn) {
1520 if (!fn) return this;
1530 if ('function' != typeof fn) throw new TypeError("fn should be a function");
1540 return this.on(this.constructor.FAILURE, fn);
155}
156
157/**
158 * Adds a single function as a listener to both SUCCESS and FAILURE.
159 *
160 * It will be executed with traditional node.js argument position:
161 * function (err, args...) {}
162 *
163 * @param {Function} fn
164 * @return {Promise} this
165 */
166
1671Promise.prototype.onResolve = function (fn) {
1680 if (!fn) return this;
1690 if ('function' != typeof fn) throw new TypeError("fn should be a function");
170
1710 this.on(this.constructor.FAILURE, function (err) {
1720 fn.apply(this, [err]);
173 });
174
1750 this.on(this.constructor.SUCCESS, function () {
1760 var args = slice(arguments);
1770 fn.apply(this, [null].concat(args));
178 });
179
1800 return this;
181}
182
183/**
184 * Creates a new promise and returns it. If `onFulfill` or
185 * `onReject` are passed, they are added as SUCCESS/ERROR callbacks
186 * to this promise after the next tick.
187 *
188 * Conforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification. Read for more detail how to use this method.
189 *
190 * ####Example:
191 *
192 * var p = new Promise;
193 * p.then(function (arg) {
194 * return arg + 1;
195 * }).then(function (arg) {
196 * throw new Error(arg + ' is an error!');
197 * }).then(null, function (err) {
198 * assert.ok(err instanceof Error);
199 * assert.equal('2 is an error', err.message);
200 * });
201 * p.complete(1);
202 *
203 * @see promises-A+ https://github.com/promises-aplus/promises-spec
204 * @param {Function} onFulFill
205 * @param {Function} [onReject]
206 * @return {Promise} newPromise
207 */
208
2091Promise.prototype.then = function (onFulfill, onReject) {
2100 var self = this
211 , retPromise = new Promise;
212
2130 if ('function' == typeof onReject) {
2140 self.onReject(handler(retPromise, onReject));
215 } else {
2160 self.onReject(retPromise.reject.bind(retPromise));
217 }
2180 if ('function' == typeof onFulfill) {
2190 self.onFulfill(handler(retPromise, onFulfill));
220 } else {
2210 self.onFulfill(retPromise.fulfill.bind(retPromise));
222 }
223
2240 return retPromise;
225};
226
227
2281function handler(retPromise, fn) {
2290 return function handler() {
2300 var args = arguments;
2310 process.nextTick(
232 function in_the_handler() {
2330 if (retPromise.domain && retPromise.domain !== process.domain) retPromise.domain.enter();
2340 var x;
235
2360 try {
2370 x = fn.apply(undefined, args);
238 } catch (err) {
2390 if (retPromise.ended && !retPromise.hasRejectListeners()) throw err;
2400 return retPromise.reject(err);
241 }
242
2430 resolve(retPromise, x);
2440 return;
245 }
246 );
247 }
248}
249
2501function resolve(promise, x) {
2510 var then;
2520 var type;
2530 var done;
2540 var reject_;
2550 var resolve_;
256
2570 type = typeof x;
2580 if ('undefined' == type) {
2590 return promise.fulfill(x);
260 }
261
2620 if (promise === x) {
2630 return promise.reject(new TypeError("promise and x are the same"));
264 }
265
2660 if (null != x) {
267
2680 if ('object' == type || 'function' == type) {
2690 try {
2700 then = x.then;
271 } catch (err) {
2720 if (promise.ended && !promise.hasRejectListeners()) throw err;
2730 return promise.reject(err);
274 }
275
2760 if ('function' == typeof then) {
2770 try {
2780 resolve_ = function () {var args = slice(arguments); resolve.apply(this, [promise].concat(args));};
2790 reject_ = promise.reject.bind(promise);
2800 done = false;
2810 return then.call(
282 x
283 , function fulfill() {
2840 if (done) return;
2850 done = true;
2860 return resolve_.apply(this, arguments);
287 }
288 , function reject() {
2890 if (done) return;
2900 done = true;
2910 return reject_.apply(this, arguments);
292 })
293 } catch (err) {
2940 if (done) return;
2950 done = true;
2960 if (promise.ended) throw err;
2970 return promise.reject(err);
298 }
299 }
300 }
301 }
302
3030 promise.fulfill(x);
304}
305
306/**
307 * Signifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught.
308 *
309 * ####Example:
310 *
311 * var p = new Promise;
312 * p.then(function(){ throw new Error('shucks') });
313 * setTimeout(function () {
314 * p.fulfill();
315 * // error was caught and swallowed by the promise returned from
316 * // p.then(). we either have to always register handlers on
317 * // the returned promises or we can do the following...
318 * }, 10);
319 *
320 * // this time we use .end() which prevents catching thrown errors
321 * var p = new Promise;
322 * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <--
323 * setTimeout(function () {
324 * p.fulfill(); // throws "shucks"
325 * }, 10);
326 *
327 * @api public
328 * @param {Function} [onReject]
329 * @return {Promise} this
330 */
331
3321Promise.prototype.end = function (onReject) {
3330 this.onReject(onReject);
3340 this.ended = true;
3350 return this;
336};
337
3381module.exports = Promise;
339

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mquery/lib/collection/collection.js

91%
12
11
1
LineHitsSource
11'use strict';
2
3/**
4 * methods a collection must implement
5 */
6
71var names = 'find findOne update remove count distict findAndModify aggregate';
81var methods = names.split(' ');
9
10/**
11 * Collection base class from which implementations inherit
12 */
13
141function Collection () {}
15
161for (var i = 0, len = methods.length; i < len; ++i) {
178 var method = methods[i];
188 Collection.prototype[method] = notImplemented(method);
19}
20
211module.exports = exports = Collection;
221Collection.methods = methods;
23
24/**
25 * creates a function which throws an implementation error
26 */
27
281function notImplemented (method) {
298 return function () {
300 throw new Error('collection.' + method + ' not implemented');
31 }
32}
33
34

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mquery/lib/collection/index.js

80%
5
4
1
LineHitsSource
11'use strict';
2
31var env = require('../env')
4
51if ('unknown' == env.type) {
60 throw new Error('Unknown environment')
7}
8
91module.exports =
10 env.isNode ? require('./node') :
11 env.isMongo ? require('./mongo') :
12 require('./browser');
13
14

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mquery/lib/collection/node.js

54%
24
13
11
LineHitsSource
11'use strict';
2
3/**
4 * Module dependencies
5 */
6
71var Collection = require('./collection');
81var utils = require('../utils');
9
101function NodeCollection (col) {
110 this.collection = col;
12}
13
14/**
15 * inherit from collection base class
16 */
17
181utils.inherits(NodeCollection, Collection);
19
20/**
21 * find(match, options, function(err, docs))
22 */
23
241NodeCollection.prototype.find = function (match, options, cb) {
250 this.collection.find(match, options, function (err, cursor) {
260 if (err) return cb(err);
27
280 cursor.toArray(cb);
29 });
30}
31
32/**
33 * findOne(match, options, function(err, doc))
34 */
35
361NodeCollection.prototype.findOne = function (match, options, cb) {
370 this.collection.findOne(match, options, cb);
38}
39
40/**
41 * count(match, options, function(err, count))
42 */
43
441NodeCollection.prototype.count = function (match, options, cb) {
450 this.collection.count(match, options, cb);
46}
47
48/**
49 * distinct(prop, match, options, function(err, count))
50 */
51
521NodeCollection.prototype.distinct = function (prop, match, options, cb) {
530 this.collection.distinct(prop, match, options, cb);
54}
55
56/**
57 * update(match, update, options, function(err[, result]))
58 */
59
601NodeCollection.prototype.update = function (match, update, options, cb) {
610 this.collection.update(match, update, options, cb);
62}
63
64/**
65 * remove(match, options, function(err[, result])
66 */
67
681NodeCollection.prototype.remove = function (match, options, cb) {
690 this.collection.remove(match, options, cb);
70}
71
72/**
73 * findAndModify(match, update, options, function(err, doc))
74 */
75
761NodeCollection.prototype.findAndModify = function (match, update, options, cb) {
770 var sort = Array.isArray(options.sort) ? options.sort : [];
780 this.collection.findAndModify(match, sort, update, options, cb);
79}
80
81/**
82 * aggregation(operators..., function(err, doc))
83 * TODO
84 */
85
86/**
87 * Streams
88 * TODO
89 */
90
91/**
92 * Expose
93 */
94
951module.exports = exports = NodeCollection;
96
97

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mquery/lib/env.js

100%
5
5
0
LineHitsSource
11'use strict';
2
31exports.isNode = 'undefined' != typeof process
4 && 'object' == typeof module
5 && 'object' == typeof global
6 && 'function' == typeof Buffer
7 && process.argv
8
91exports.isMongo = !exports.isNode
10 && 'function' == typeof printjson
11 && 'function' == typeof ObjectId
12 && 'function' == typeof rs
13 && 'function' == typeof sh;
14
151exports.isBrowser = !exports.isNode
16 && !exports.isMongo
17 && 'undefined' != typeof window;
18
191exports.type = exports.isNode ? 'node'
20 : exports.isMongo ? 'mongo'
21 : exports.isBrowser ? 'browser'
22 : 'unknown'
23

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mquery/lib/mquery.js

12%
691
85
606
LineHitsSource
11'use strict';
2
3/**
4 * Dependencies
5 */
6
71var slice = require('sliced')
81var assert = require('assert')
91var util = require('util')
101var utils = require('./utils')
111var debug = require('debug')('mquery');
12
13/**
14 * Query constructor used for building queries.
15 *
16 * ####Example:
17 *
18 * var query = new Query({ name: 'mquery' });
19 * query.setOptions({ collection: moduleCollection })
20 * query.where('age').gte(21).exec(callback);
21 *
22 * @param {Object} [criteria]
23 * @param {Object} [options]
24 * @api public
25 */
26
271function Query (criteria, options) {
281 if (!(this instanceof Query))
290 return new Query(criteria, options);
30
311 var proto = this.constructor.prototype;
32
331 this.op = proto.op || undefined;
34
351 this.options = {};
361 this.setOptions(proto.options);
37
381 this._conditions = proto._conditions
39 ? utils.clone(proto._conditions)
40 : {};
41
421 this._fields = proto._fields
43 ? utils.clone(proto._fields)
44 : undefined;
45
461 this._update = proto._update
47 ? utils.clone(proto._update)
48 : undefined;
49
501 this._path = proto._path || undefined;
511 this._distinct = proto._distinct || undefined;
521 this._collection = proto._collection || undefined;
53
541 if (options) {
550 this.setOptions(options);
56 }
57
581 if (criteria) {
590 if (criteria.find && criteria.remove && criteria.update) {
60 // quack quack!
610 this.collection(criteria);
62 } else {
630 this.find(criteria);
64 }
65 }
66}
67
68/**
69 * This is a parameter that the user can set which determines if mquery
70 * uses $within or $geoWithin for queries. It defaults to true which
71 * means $geoWithin will be used. If using MongoDB < 2.4 you should
72 * set this to false.
73 *
74 * @api public
75 * @property use$geoWithin
76 */
77
781var $withinCmd = '$geoWithin';
791Object.defineProperty(Query, 'use$geoWithin', {
801 get: function ( ) { return $withinCmd == '$geoWithin' }
81 , set: function (v) {
820 if (true === v) {
83 // mongodb >= 2.4
840 $withinCmd = '$geoWithin';
85 } else {
860 $withinCmd = '$within';
87 }
88 }
89});
90
91/**
92 * Converts this query to a constructor function with all arguments and options retained.
93 *
94 * ####Example
95 *
96 * // Create a query that will read documents with a "video" category from
97 * // `aCollection` on the primary node in the replica-set unless it is down,
98 * // in which case we'll read from a secondary node.
99 * var query = mquery({ category: 'video' })
100 * query.setOptions({ collection: aCollection, read: 'primaryPreferred' });
101 *
102 * // create a constructor based off these settings
103 * var Video = query.toConstructor();
104 *
105 * // Video is now a subclass of mquery() and works the same way but with the
106 * // default query parameters and options set.
107 *
108 * // run a query with the previous settings but filter for movies with names
109 * // that start with "Life".
110 * Video().where({ name: /^Life/ }).exec(cb);
111 *
112 * @return {Query} new Query
113 * @api public
114 */
115
1161Query.prototype.toConstructor = function toConstructor () {
1170 function CustomQuery (criteria, options) {
1180 if (!(this instanceof CustomQuery))
1190 return new CustomQuery(criteria, options);
1200 Query.call(this, criteria, options);
121 }
122
1230 utils.inherits(CustomQuery, Query);
124
125 // set inherited defaults
1260 var p = CustomQuery.prototype;
127
1280 p.options = {};
1290 p.setOptions(this.options);
130
1310 p.op = this.op;
1320 p._conditions = utils.clone(this._conditions);
1330 p._fields = utils.clone(this._fields);
1340 p._update = utils.clone(this._update);
1350 p._path = this._path;
1360 p._distict = this._distinct;
1370 p._collection = this._collection;
138
1390 return CustomQuery;
140}
141
142/**
143 * Sets query options.
144 *
145 * ####Options:
146 *
147 * - [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors) *
148 * - [sort](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsort(\)%7D%7D) *
149 * - [limit](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D) *
150 * - [skip](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D) *
151 * - [maxScan](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan) *
152 * - [batchSize](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D) *
153 * - [comment](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment) *
154 * - [snapshot](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D) *
155 * - [hint](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint) *
156 * - [slaveOk](http://docs.mongodb.org/manual/applications/replication/#read-preference) *
157 * - [safe](http://www.mongodb.org/display/DOCS/getLastError+Command)
158 * - collection the collection to query against
159 *
160 * _* denotes a query helper method is also available_
161 *
162 * @param {Object} options
163 * @api public
164 */
165
1661Query.prototype.setOptions = function (options) {
1671 if (!(options && utils.isObject(options)))
1681 return this;
169
170 // set arbitrary options
1710 var methods = utils.keys(options)
172 , method
173
1740 for (var i = 0; i < methods.length; ++i) {
1750 method = methods[i];
176
177 // use methods if exist (safer option manipulation)
1780 if ('function' == typeof this[method]) {
1790 var args = utils.isArray(options[method])
180 ? options[method]
181 : [options[method]];
1820 this[method].apply(this, args)
183 } else {
1840 this.options[method] = options[method];
185 }
186 }
187
1880 return this;
189}
190
191/**
192 * Sets this Querys collection.
193 *
194 * @param {Collection} coll
195 * @return {Query} this
196 */
197
1981Query.prototype.collection = function collection (coll) {
1990 this._collection = new Query.Collection(coll);
200
2010 return this;
202}
203
204/**
205 * Specifies a `$where` condition
206 *
207 * Use `$where` when you need to select documents using a JavaScript expression.
208 *
209 * ####Example
210 *
211 * query.$where('this.comments.length > 10 || this.name.length > 5')
212 *
213 * query.$where(function () {
214 * return this.comments.length > 10 || this.name.length > 5;
215 * })
216 *
217 * @param {String|Function} js javascript string or function
218 * @return {Query} this
219 * @memberOf Query
220 * @method $where
221 * @api public
222 */
223
2241Query.prototype.$where = function (js) {
2250 this._conditions.$where = js;
2260 return this;
227}
228
229/**
230 * Specifies a `path` for use with chaining.
231 *
232 * ####Example
233 *
234 * // instead of writing:
235 * User.find({age: {$gte: 21, $lte: 65}}, callback);
236 *
237 * // we can instead write:
238 * User.where('age').gte(21).lte(65);
239 *
240 * // passing query conditions is permitted
241 * User.find().where({ name: 'vonderful' })
242 *
243 * // chaining
244 * User
245 * .where('age').gte(21).lte(65)
246 * .where('name', /^vonderful/i)
247 * .where('friends').slice(10)
248 * .exec(callback)
249 *
250 * @param {String} [path]
251 * @param {Object} [val]
252 * @return {Query} this
253 * @api public
254 */
255
2561Query.prototype.where = function () {
2570 if (!arguments.length) return this;
2580 if (!this.op) this.op = 'find';
259
2600 var type = typeof arguments[0];
261
2620 if ('string' == type) {
2630 this._path = arguments[0];
264
2650 if (2 === arguments.length) {
2660 this._conditions[this._path] = arguments[1];
267 }
268
2690 return this;
270 }
271
2720 if ('object' == type && !Array.isArray(arguments[0])) {
2730 return this.merge(arguments[0]);
274 }
275
2760 throw new TypeError('path must be a string or object');
277}
278
279/**
280 * Specifies the complementary comparison value for paths specified with `where()`
281 *
282 * ####Example
283 *
284 * User.where('age').equals(49);
285 *
286 * // is the same as
287 *
288 * User.where('age', 49);
289 *
290 * @param {Object} val
291 * @return {Query} this
292 * @api public
293 */
294
2951Query.prototype.equals = function equals (val) {
2960 this._ensurePath('equals');
2970 var path = this._path;
2980 this._conditions[path] = val;
2990 return this;
300}
301
302/**
303 * Specifies arguments for an `$or` condition.
304 *
305 * ####Example
306 *
307 * query.or([{ color: 'red' }, { status: 'emergency' }])
308 *
309 * @param {Array} array array of conditions
310 * @return {Query} this
311 * @api public
312 */
313
3141Query.prototype.or = function or (array) {
3150 var or = this._conditions.$or || (this._conditions.$or = []);
3160 if (!utils.isArray(array)) array = [array];
3170 or.push.apply(or, array);
3180 return this;
319}
320
321/**
322 * Specifies arguments for a `$nor` condition.
323 *
324 * ####Example
325 *
326 * query.nor([{ color: 'green' }, { status: 'ok' }])
327 *
328 * @param {Array} array array of conditions
329 * @return {Query} this
330 * @api public
331 */
332
3331Query.prototype.nor = function nor (array) {
3340 var nor = this._conditions.$nor || (this._conditions.$nor = []);
3350 if (!utils.isArray(array)) array = [array];
3360 nor.push.apply(nor, array);
3370 return this;
338}
339
340/**
341 * Specifies arguments for a `$and` condition.
342 *
343 * ####Example
344 *
345 * query.and([{ color: 'green' }, { status: 'ok' }])
346 *
347 * @see $and http://docs.mongodb.org/manual/reference/operator/and/
348 * @param {Array} array array of conditions
349 * @return {Query} this
350 * @api public
351 */
352
3531Query.prototype.and = function and (array) {
3540 var and = this._conditions.$and || (this._conditions.$and = []);
3550 if (!Array.isArray(array)) array = [array];
3560 and.push.apply(and, array);
3570 return this;
358}
359
360/**
361 * Specifies a $gt query condition.
362 *
363 * When called with one argument, the most recent path passed to `where()` is used.
364 *
365 * ####Example
366 *
367 * Thing.find().where('age').gt(21)
368 *
369 * // or
370 * Thing.find().gt('age', 21)
371 *
372 * @method gt
373 * @memberOf Query
374 * @param {String} [path]
375 * @param {Number} val
376 * @api public
377 */
378
379/**
380 * Specifies a $gte query condition.
381 *
382 * When called with one argument, the most recent path passed to `where()` is used.
383 *
384 * @method gte
385 * @memberOf Query
386 * @param {String} [path]
387 * @param {Number} val
388 * @api public
389 */
390
391/**
392 * Specifies a $lt query condition.
393 *
394 * When called with one argument, the most recent path passed to `where()` is used.
395 *
396 * @method lt
397 * @memberOf Query
398 * @param {String} [path]
399 * @param {Number} val
400 * @api public
401 */
402
403/**
404 * Specifies a $lte query condition.
405 *
406 * When called with one argument, the most recent path passed to `where()` is used.
407 *
408 * @method lte
409 * @memberOf Query
410 * @param {String} [path]
411 * @param {Number} val
412 * @api public
413 */
414
415/**
416 * Specifies a $ne query condition.
417 *
418 * When called with one argument, the most recent path passed to `where()` is used.
419 *
420 * @method ne
421 * @memberOf Query
422 * @param {String} [path]
423 * @param {Number} val
424 * @api public
425 */
426
427/**
428 * Specifies an $in query condition.
429 *
430 * When called with one argument, the most recent path passed to `where()` is used.
431 *
432 * @method in
433 * @memberOf Query
434 * @param {String} [path]
435 * @param {Number} val
436 * @api public
437 */
438
439/**
440 * Specifies an $nin query condition.
441 *
442 * When called with one argument, the most recent path passed to `where()` is used.
443 *
444 * @method nin
445 * @memberOf Query
446 * @param {String} [path]
447 * @param {Number} val
448 * @api public
449 */
450
451/**
452 * Specifies an $all query condition.
453 *
454 * When called with one argument, the most recent path passed to `where()` is used.
455 *
456 * @method all
457 * @memberOf Query
458 * @param {String} [path]
459 * @param {Number} val
460 * @api public
461 */
462
463/**
464 * Specifies a $size query condition.
465 *
466 * When called with one argument, the most recent path passed to `where()` is used.
467 *
468 * @method size
469 * @memberOf Query
470 * @param {String} [path]
471 * @param {Number} val
472 * @api public
473 */
474
475/**
476 * Specifies a $regex query condition.
477 *
478 * When called with one argument, the most recent path passed to `where()` is used.
479 *
480 * @method regex
481 * @memberOf Query
482 * @param {String} [path]
483 * @param {Number} val
484 * @api public
485 */
486
487/**
488 * Specifies a $maxDistance query condition.
489 *
490 * When called with one argument, the most recent path passed to `where()` is used.
491 *
492 * @method maxDistance
493 * @memberOf Query
494 * @param {String} [path]
495 * @param {Number} val
496 * @api public
497 */
498
499/*!
500 * gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance
501 *
502 * Thing.where('type').nin(array)
503 */
504
5051'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {
50611 Query.prototype[$conditional] = function () {
5070 var path, val;
508
5090 if (1 === arguments.length) {
5100 this._ensurePath($conditional);
5110 val = arguments[0];
5120 path = this._path;
513 } else {
5140 val = arguments[1];
5150 path = arguments[0];
516 }
517
5180 var conds = this._conditions[path] || (this._conditions[path] = {});
5190 conds['$' + $conditional] = val;
5200 return this;
521 };
522})
523
524/**
525 * Specifies a `$mod` condition
526 *
527 * @param {String} [path]
528 * @param {Number} val
529 * @return {Query} this
530 * @api public
531 */
532
5331Query.prototype.mod = function () {
5340 var val, path;
535
5360 if (1 === arguments.length) {
5370 this._ensurePath('mod')
5380 val = arguments[0];
5390 path = this._path;
5400 } else if (2 === arguments.length && !utils.isArray(arguments[1])) {
5410 this._ensurePath('mod')
5420 val = slice(arguments);
5430 path = this._path;
5440 } else if (3 === arguments.length) {
5450 val = slice(arguments, 1);
5460 path = arguments[0];
547 } else {
5480 val = arguments[1];
5490 path = arguments[0];
550 }
551
5520 var conds = this._conditions[path] || (this._conditions[path] = {});
5530 conds.$mod = val;
5540 return this;
555}
556
557/**
558 * Specifies an `$exists` condition
559 *
560 * ####Example
561 *
562 * // { name: { $exists: true }}
563 * Thing.where('name').exists()
564 * Thing.where('name').exists(true)
565 * Thing.find().exists('name')
566 *
567 * // { name: { $exists: false }}
568 * Thing.where('name').exists(false);
569 * Thing.find().exists('name', false);
570 *
571 * @param {String} [path]
572 * @param {Number} val
573 * @return {Query} this
574 * @api public
575 */
576
5771Query.prototype.exists = function () {
5780 var path, val;
579
5800 if (0 === arguments.length) {
5810 this._ensurePath('exists');
5820 path = this._path;
5830 val = true;
5840 } else if (1 === arguments.length) {
5850 if ('boolean' === typeof arguments[0]) {
5860 this._ensurePath('exists');
5870 path = this._path;
5880 val = arguments[0];
589 } else {
5900 path = arguments[0];
5910 val = true;
592 }
5930 } else if (2 === arguments.length) {
5940 path = arguments[0];
5950 val = arguments[1];
596 }
597
5980 var conds = this._conditions[path] || (this._conditions[path] = {});
5990 conds.$exists = val;
6000 return this;
601}
602
603/**
604 * Specifies an `$elemMatch` condition
605 *
606 * ####Example
607 *
608 * query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
609 *
610 * query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
611 *
612 * query.elemMatch('comment', function (elem) {
613 * elem.where('author').equals('autobot');
614 * elem.where('votes').gte(5);
615 * })
616 *
617 * query.where('comment').elemMatch(function (elem) {
618 * elem.where({ author: 'autobot' });
619 * elem.where('votes').gte(5);
620 * })
621 *
622 * @param {String|Object|Function} path
623 * @param {Object|Function} criteria
624 * @return {Query} this
625 * @api public
626 */
627
6281Query.prototype.elemMatch = function () {
6290 if (null == arguments[0])
6300 throw new TypeError("Invalid argument");
631
6320 var fn, path, criteria;
633
6340 if ('function' === typeof arguments[0]) {
6350 this._ensurePath('elemMatch');
6360 path = this._path;
6370 fn = arguments[0];
6380 } else if (utils.isObject(arguments[0])) {
6390 this._ensurePath('elemMatch');
6400 path = this._path;
6410 criteria = arguments[0];
6420 } else if ('function' === typeof arguments[1]) {
6430 path = arguments[0];
6440 fn = arguments[1];
6450 } else if (arguments[1] && utils.isObject(arguments[1])) {
6460 path = arguments[0];
6470 criteria = arguments[1];
648 } else {
6490 throw new TypeError("Invalid argument");
650 }
651
6520 if (fn) {
6530 criteria = new Query;
6540 fn(criteria);
6550 criteria = criteria._conditions;
656 }
657
6580 var conds = this._conditions[path] || (this._conditions[path] = {});
6590 conds.$elemMatch = criteria;
6600 return this;
661}
662
663// Spatial queries
664
665/**
666 * Sugar for geo-spatial queries.
667 *
668 * ####Example
669 *
670 * query.within().box()
671 * query.within().circle()
672 * query.within().geometry()
673 *
674 * query.where('loc').within({ center: [50,50], radius: 10, unique: true, spherical: true });
675 * query.where('loc').within({ box: [[40.73, -73.9], [40.7, -73.988]] });
676 * query.where('loc').within({ polygon: [[],[],[],[]] });
677 *
678 * query.where('loc').within([], [], []) // polygon
679 * query.where('loc').within([], []) // box
680 * query.where('loc').within({ type: 'LineString', coordinates: [...] }); // geometry
681 *
682 * ####NOTE:
683 *
684 * Must be used after `where()`.
685 *
686 * @memberOf Query
687 * @return {Query} this
688 * @api public
689 */
690
6911Query.prototype.within = function within () {
692 // opinionated, must be used after where
6930 this._ensurePath('within');
6940 this._geoComparison = $withinCmd;
695
6960 if (0 === arguments.length) {
6970 return this;
698 }
699
7000 if (2 === arguments.length) {
7010 return this.box.apply(this, arguments);
7020 } else if (2 < arguments.length) {
7030 return this.polygon.apply(this, arguments);
704 }
705
7060 var area = arguments[0];
707
7080 if (!area)
7090 throw new TypeError('Invalid argument');
710
7110 if (area.center)
7120 return this.circle(area);
713
7140 if (area.box)
7150 return this.box.apply(this, area.box);
716
7170 if (area.polygon)
7180 return this.polygon.apply(this, area.polygon);
719
7200 if (area.type && area.coordinates)
7210 return this.geometry(area);
722
7230 throw new TypeError('Invalid argument');
724}
725
726/**
727 * Specifies a $box condition
728 *
729 * ####Example
730 *
731 * var lowerLeft = [40.73083, -73.99756]
732 * var upperRight= [40.741404, -73.988135]
733 *
734 * query.where('loc').within().box(lowerLeft, upperRight)
735 * query.box('loc', lowerLeft, upperRight )
736 *
737 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
738 * @see Query#within #query_Query-within
739 * @param {String} path
740 * @param {Object} val
741 * @return {Query} this
742 * @api public
743 */
744
7451Query.prototype.box = function () {
7460 var path, box;
747
7480 if (3 === arguments.length) {
749 // box('loc', [], [])
7500 path = arguments[0];
7510 box = [arguments[1], arguments[2]];
7520 } else if (2 === arguments.length) {
753 // box([], [])
7540 this._ensurePath('box');
7550 path = this._path;
7560 box = [arguments[0], arguments[1]];
757 } else {
7580 throw new TypeError("Invalid argument");
759 }
760
7610 var conds = this._conditions[path] || (this._conditions[path] = {});
7620 conds[this._geoComparison || $withinCmd] = { '$box': box };
7630 return this;
764}
765
766/**
767 * Specifies a $polygon condition
768 *
769 * ####Example
770 *
771 * query.where('loc').within().polygon([10,20], [13, 25], [7,15])
772 * query.polygon('loc', [10,20], [13, 25], [7,15])
773 *
774 * @param {String|Array} [path]
775 * @param {Array|Object} [val]
776 * @return {Query} this
777 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
778 * @api public
779 */
780
7811Query.prototype.polygon = function () {
7820 var val, path;
783
7840 if ('string' == typeof arguments[0]) {
785 // polygon('loc', [],[],[])
7860 path = arguments[0];
7870 val = slice(arguments, 1);
788 } else {
789 // polygon([],[],[])
7900 this._ensurePath('polygon');
7910 path = this._path;
7920 val = slice(arguments);
793 }
794
7950 var conds = this._conditions[path] || (this._conditions[path] = {});
7960 conds[this._geoComparison || $withinCmd] = { '$polygon': val };
7970 return this;
798}
799
800/**
801 * Specifies a $center or $centerSphere condition.
802 *
803 * ####Example
804 *
805 * var area = { center: [50, 50], radius: 10, unique: true }
806 * query.where('loc').within().circle(area)
807 * query.center('loc', area);
808 *
809 * // for spherical calculations
810 * var area = { center: [50, 50], radius: 10, unique: true, spherical: true }
811 * query.where('loc').within().circle(area)
812 * query.center('loc', area);
813 *
814 * @param {String} [path]
815 * @param {Object} area
816 * @return {Query} this
817 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
818 * @api public
819 */
820
8211Query.prototype.circle = function () {
8220 var path, val;
823
8240 if (1 === arguments.length) {
8250 this._ensurePath('circle');
8260 path = this._path;
8270 val = arguments[0];
8280 } else if (2 === arguments.length) {
8290 path = arguments[0];
8300 val = arguments[1];
831 } else {
8320 throw new TypeError("Invalid argument");
833 }
834
8350 if (!('radius' in val && val.center))
8360 throw new Error('center and radius are required');
837
8380 var conds = this._conditions[path] || (this._conditions[path] = {});
839
8400 var type = val.spherical
841 ? '$centerSphere'
842 : '$center';
843
8440 var wKey = this._geoComparison || $withinCmd;
8450 conds[wKey] = {};
8460 conds[wKey][type] = [val.center, val.radius];
847
8480 if ('unique' in val)
8490 conds[wKey].$uniqueDocs = !! val.unique;
850
8510 return this;
852}
853
854/**
855 * Specifies a `$near` or `$nearSphere` condition
856 *
857 * These operators return documents sorted by distance.
858 *
859 * ####Example
860 *
861 * query.where('loc').near({ center: [10, 10] });
862 * query.where('loc').near({ center: [10, 10], maxDistance: 5 });
863 * query.where('loc').near({ center: [10, 10], maxDistance: 5, spherical: true });
864 * query.near('loc', { center: [10, 10], maxDistance: 5 });
865 * query.near({ center: { type: 'Point', coordinates: [..] }})
866 * query.near().geometry({ type: 'Point', coordinates: [..] })
867 *
868 * @param {String} [path]
869 * @param {Object} val
870 * @return {Query} this
871 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
872 * @api public
873 */
874
8751Query.prototype.near = function near () {
8760 var path, val;
877
8780 this._geoComparison = '$near';
879
8800 if (0 === arguments.length) {
8810 return this;
8820 } else if (1 === arguments.length) {
8830 this._ensurePath('near');
8840 path = this._path;
8850 val = arguments[0];
8860 } else if (2 === arguments.length) {
8870 path = arguments[0];
8880 val = arguments[1];
889 } else {
8900 throw new TypeError("Invalid argument");
891 }
892
8930 if (!val.center) {
8940 throw new Error('center is required');
895 }
896
8970 var conds = this._conditions[path] || (this._conditions[path] = {});
898
8990 var type = val.spherical
900 ? '$nearSphere'
901 : '$near';
902
903 // center could be a GeoJSON object or an Array
9040 if (Array.isArray(val.center)) {
9050 conds[type] = val.center;
906 } else {
907 // GeoJSON?
9080 if (val.center.type != 'Point' || !Array.isArray(val.center.coordinates)) {
9090 throw new Error(util.format("Invalid GeoJSON specified for %s", type));
910 }
9110 conds[type] = { $geometry : val.center };
912 }
913
9140 var radius = 'maxDistance' in val
915 ? val.maxDistance
916 : null;
917
9180 if (null != radius) {
9190 conds.$maxDistance = radius;
920 }
921
9220 return this;
923}
924
925/**
926 * Declares an intersects query for `geometry()`.
927 *
928 * ####Example
929 *
930 * query.where('path').intersects().geometry({
931 * type: 'LineString'
932 * , coordinates: [[180.0, 11.0], [180, 9.0]]
933 * })
934 *
935 * query.where('path').intersects({
936 * type: 'LineString'
937 * , coordinates: [[180.0, 11.0], [180, 9.0]]
938 * })
939 *
940 * @param {Object} [arg]
941 * @return {Query} this
942 * @api public
943 */
944
9451Query.prototype.intersects = function intersects () {
946 // opinionated, must be used after where
9470 this._ensurePath('intersects');
948
9490 this._geoComparison = '$geoIntersects';
950
9510 if (0 === arguments.length) {
9520 return this;
953 }
954
9550 var area = arguments[0];
956
9570 if (null != area && area.type && area.coordinates)
9580 return this.geometry(area);
959
9600 throw new TypeError('Invalid argument');
961}
962
963/**
964 * Specifies a `$geometry` condition
965 *
966 * ####Example
967 *
968 * var polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]]
969 * query.where('loc').within().geometry({ type: 'Polygon', coordinates: polyA })
970 *
971 * // or
972 * var polyB = [[ 0, 0 ], [ 1, 1 ]]
973 * query.where('loc').within().geometry({ type: 'LineString', coordinates: polyB })
974 *
975 * // or
976 * var polyC = [ 0, 0 ]
977 * query.where('loc').within().geometry({ type: 'Point', coordinates: polyC })
978 *
979 * // or
980 * query.where('loc').intersects().geometry({ type: 'Point', coordinates: polyC })
981 *
982 * ####NOTE:
983 *
984 * `geometry()` **must** come after either `intersects()` or `within()`.
985 *
986 * The `object` argument must contain `type` and `coordinates` properties.
987 * - type {String}
988 * - coordinates {Array}
989 *
990 * The most recent path passed to `where()` is used.
991 *
992 * @param {Object} object Must contain a `type` property which is a String and a `coordinates` property which is an Array. See the examples.
993 * @return {Query} this
994 * @see http://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry
995 * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
996 * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/
997 * @api public
998 */
999
10001Query.prototype.geometry = function geometry () {
10010 if (!('$within' == this._geoComparison ||
1002 '$geoWithin' == this._geoComparison ||
1003 '$near' == this._geoComparison ||
1004 '$geoIntersects' == this._geoComparison)) {
10050 throw new Error('geometry() must come after `within()`, `intersects()`, or `near()');
1006 }
1007
10080 var val, path;
1009
10100 if (1 === arguments.length) {
10110 this._ensurePath('geometry');
10120 path = this._path;
10130 val = arguments[0];
1014 } else {
10150 throw new TypeError("Invalid argument");
1016 }
1017
10180 if (!(val.type && Array.isArray(val.coordinates))) {
10190 throw new TypeError('Invalid argument');
1020 }
1021
10220 var conds = this._conditions[path] || (this._conditions[path] = {});
10230 conds[this._geoComparison] = { $geometry: val };
1024
10250 return this;
1026}
1027
1028// end spatial
1029
1030/**
1031 * Specifies which document fields to include or exclude
1032 *
1033 * ####String syntax
1034 *
1035 * When passing a string, prefixing a path with `-` will flag that path as excluded. When a path does not have the `-` prefix, it is included.
1036 *
1037 * ####Example
1038 *
1039 * // include a and b, exclude c
1040 * query.select('a b -c');
1041 *
1042 * // or you may use object notation, useful when
1043 * // you have keys already prefixed with a "-"
1044 * query.select({a: 1, b: 1, c: 0});
1045 *
1046 * ####Note
1047 *
1048 * Cannot be used with `distinct()`
1049 *
1050 * @param {Object|String} arg
1051 * @return {Query} this
1052 * @see SchemaType
1053 * @api public
1054 */
1055
10561Query.prototype.select = function select () {
10570 var arg = arguments[0];
10580 if (!arg) return this;
1059
10600 if (arguments.length !== 1) {
10610 throw new Error("Invalid select: select only takes 1 argument");
1062 }
1063
10640 this._validate('select');
1065
10660 var fields = this._fields || (this._fields = {});
10670 var type = typeof arg;
1068
10690 if ('string' == type || 'object' == type && 'number' == typeof arg.length && !Array.isArray(arg)) {
10700 if ('string' == type)
10710 arg = arg.split(/\s+/);
1072
10730 for (var i = 0, len = arg.length; i < len; ++i) {
10740 var field = arg[i];
10750 if (!field) continue;
10760 var include = '-' == field[0] ? 0 : 1;
10770 if (include === 0) field = field.substring(1);
10780 fields[field] = include;
1079 }
1080
10810 return this;
1082 }
1083
10840 if (utils.isObject(arg) && !Array.isArray(arg)) {
10850 var keys = utils.keys(arg);
10860 for (var i = 0; i < keys.length; ++i) {
10870 fields[keys[i]] = arg[keys[i]];
1088 }
10890 return this;
1090 }
1091
10920 throw new TypeError('Invalid select() argument. Must be string or object.');
1093}
1094
1095/**
1096 * Specifies a $slice condition for a `path`
1097 *
1098 * ####Example
1099 *
1100 * query.slice('comments', 5)
1101 * query.slice('comments', -5)
1102 * query.slice('comments', [10, 5])
1103 * query.where('comments').slice(5)
1104 * query.where('comments').slice([-10, 5])
1105 *
1106 * @param {String} [path]
1107 * @param {Number} val number/range of elements to slice
1108 * @return {Query} this
1109 * @see mongodb http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements
1110 * @api public
1111 */
1112
11131Query.prototype.slice = function () {
11140 if (0 === arguments.length)
11150 return this;
1116
11170 this._validate('slice');
1118
11190 var path, val;
1120
11210 if (1 === arguments.length) {
11220 this._ensurePath('slice');
11230 path = this._path;
11240 val = arguments[0];
11250 } else if (2 === arguments.length) {
11260 if ('number' === typeof arguments[0]) {
11270 this._ensurePath('slice');
11280 path = this._path;
11290 val = slice(arguments);
1130 } else {
11310 path = arguments[0];
11320 val = arguments[1];
1133 }
11340 } else if (3 === arguments.length) {
11350 path = arguments[0];
11360 val = slice(arguments, 1);
1137 }
1138
11390 var myFields = this._fields || (this._fields = {});
11400 myFields[path] = { '$slice': val };
11410 return this;
1142}
1143
1144/**
1145 * Sets the sort order
1146 *
1147 * If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.
1148 *
1149 * If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with `-` which will be treated as descending.
1150 *
1151 * ####Example
1152 *
1153 * // these are equivalent
1154 * query.sort({ field: 'asc', test: -1 });
1155 * query.sort('field -test');
1156 *
1157 * ####Note
1158 *
1159 * Cannot be used with `distinct()`
1160 *
1161 * @param {Object|String} arg
1162 * @return {Query} this
1163 * @api public
1164 */
1165
11661Query.prototype.sort = function (arg) {
11670 if (!arg) return this;
1168
11690 this._validate('sort');
1170
11710 var type = typeof arg;
1172
11730 if (1 === arguments.length && 'string' == type) {
11740 arg = arg.split(/\s+/);
1175
11760 for (var i = 0, len = arg.length; i < len; ++i) {
11770 var field = arg[i];
11780 if (!field) continue;
11790 var ascend = '-' == field[0] ? -1 : 1;
11800 if (ascend === -1) field = field.substring(1);
11810 push(this.options, field, ascend);
1182 }
1183
11840 return this;
1185 }
1186
11870 if (utils.isObject(arg)) {
11880 var keys = utils.keys(arg);
11890 for (var i = 0; i < keys.length; ++i) {
11900 var field = keys[i];
11910 push(this.options, field, arg[field]);
1192 }
1193
11940 return this;
1195 }
1196
11970 throw new TypeError('Invalid sort() argument. Must be a string or object.');
1198}
1199
1200/*!
1201 * @ignore
1202 */
1203
12041function push (opts, field, value) {
12050 var val = String(value || 1).toLowerCase();
12060 if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {
12070 if (utils.isArray(value)) value = '['+value+']';
12080 throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');
1209 }
1210 // store `sort` in a sane format
12110 var s = opts.sort || (opts.sort = {});
12120 var valueStr = value.toString()
1213 .replace("asc", "1")
1214 .replace("ascending", "1")
1215 .replace("desc", "-1")
1216 .replace("descending", "-1");
12170 s[field] = parseInt(valueStr);
1218}
1219
1220/**
1221 * Specifies the limit option.
1222 *
1223 * ####Example
1224 *
1225 * query.limit(20)
1226 *
1227 * ####Note
1228 *
1229 * Cannot be used with `distinct()`
1230 *
1231 * @method limit
1232 * @memberOf Query
1233 * @param {Number} val
1234 * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D
1235 * @api public
1236 */
1237/**
1238 * Specifies the skip option.
1239 *
1240 * ####Example
1241 *
1242 * query.skip(100).limit(20)
1243 *
1244 * ####Note
1245 *
1246 * Cannot be used with `distinct()`
1247 *
1248 * @method skip
1249 * @memberOf Query
1250 * @param {Number} val
1251 * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D
1252 * @api public
1253 */
1254/**
1255 * Specifies the maxScan option.
1256 *
1257 * ####Example
1258 *
1259 * query.maxScan(100)
1260 *
1261 * ####Note
1262 *
1263 * Cannot be used with `distinct()`
1264 *
1265 * @method maxScan
1266 * @memberOf Query
1267 * @param {Number} val
1268 * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan
1269 * @api public
1270 */
1271/**
1272 * Specifies the batchSize option.
1273 *
1274 * ####Example
1275 *
1276 * query.batchSize(100)
1277 *
1278 * ####Note
1279 *
1280 * Cannot be used with `distinct()`
1281 *
1282 * @method batchSize
1283 * @memberOf Query
1284 * @param {Number} val
1285 * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D
1286 * @api public
1287 */
1288/**
1289 * Specifies the `comment` option.
1290 *
1291 * ####Example
1292 *
1293 * query.comment('login query')
1294 *
1295 * ####Note
1296 *
1297 * Cannot be used with `distinct()`
1298 *
1299 * @method comment
1300 * @memberOf Query
1301 * @param {Number} val
1302 * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment
1303 * @api public
1304 */
1305
1306/*!
1307 * limit, skip, maxScan, batchSize, comment
1308 *
1309 * Sets these associated options.
1310 *
1311 * query.comment('feed query');
1312 */
1313
13141;['limit', 'skip', 'maxScan', 'batchSize', 'comment'].forEach(function (method) {
13155 Query.prototype[method] = function (v) {
13160 this._validate(method);
13170 this.options[method] = v;
13180 return this;
1319 };
1320})
1321
1322/**
1323 * Specifies this query as a `snapshot` query.
1324 *
1325 * ####Example
1326 *
1327 * mquery().snapshot() // true
1328 * mquery().snapshot(true)
1329 * mquery().snapshot(false)
1330 *
1331 * ####Note
1332 *
1333 * Cannot be used with `distinct()`
1334 *
1335 * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D
1336 * @return {Query} this
1337 * @api public
1338 */
1339
13401Query.prototype.snapshot = function () {
13410 this._validate('snapshot');
1342
13430 this.options.snapshot = arguments.length
1344 ? !! arguments[0]
1345 : true
1346
13470 return this;
1348}
1349
1350/**
1351 * Sets query hints.
1352 *
1353 * ####Example
1354 *
1355 * query.hint({ indexA: 1, indexB: -1})
1356 *
1357 * ####Note
1358 *
1359 * Cannot be used with `distinct()`
1360 *
1361 * @param {Object} val a hint object
1362 * @return {Query} this
1363 * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint
1364 * @api public
1365 */
1366
13671Query.prototype.hint = function () {
13680 if (0 === arguments.length) return this;
1369
13700 this._validate('hint');
1371
13720 var arg = arguments[0];
13730 if (utils.isObject(arg)) {
13740 var hint = this.options.hint || (this.options.hint = {});
1375
1376 // must keep object keys in order so don't use Object.keys()
13770 for (var k in arg) {
13780 hint[k] = arg[k];
1379 }
1380
13810 return this;
1382 }
1383
13840 throw new TypeError('Invalid hint. ' + arg);
1385}
1386
1387/**
1388 * Sets the slaveOk option. _Deprecated_ in MongoDB 2.2 in favor of read preferences.
1389 *
1390 * ####Example:
1391 *
1392 * query.slaveOk() // true
1393 * query.slaveOk(true)
1394 * query.slaveOk(false)
1395 *
1396 * @deprecated use read() preferences instead if on mongodb >= 2.2
1397 * @param {Boolean} v defaults to true
1398 * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference
1399 * @see read()
1400 * @return {Query} this
1401 * @api public
1402 */
1403
14041Query.prototype.slaveOk = function (v) {
14050 this.options.slaveOk = arguments.length ? !!v : true;
14060 return this;
1407}
1408
1409/**
1410 * Sets the readPreference option for the query.
1411 *
1412 * ####Example:
1413 *
1414 * new Query().read('primary')
1415 * new Query().read('p') // same as primary
1416 *
1417 * new Query().read('primaryPreferred')
1418 * new Query().read('pp') // same as primaryPreferred
1419 *
1420 * new Query().read('secondary')
1421 * new Query().read('s') // same as secondary
1422 *
1423 * new Query().read('secondaryPreferred')
1424 * new Query().read('sp') // same as secondaryPreferred
1425 *
1426 * new Query().read('nearest')
1427 * new Query().read('n') // same as nearest
1428 *
1429 * // you can also use mongodb.ReadPreference class to also specify tags
1430 * new Query().read(mongodb.ReadPreference('secondary', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }]))
1431 *
1432 * ####Preferences:
1433 *
1434 * primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
1435 * secondary Read from secondary if available, otherwise error.
1436 * primaryPreferred Read from primary if available, otherwise a secondary.
1437 * secondaryPreferred Read from a secondary if available, otherwise read from the primary.
1438 * nearest All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
1439 *
1440 * Aliases
1441 *
1442 * p primary
1443 * pp primaryPreferred
1444 * s secondary
1445 * sp secondaryPreferred
1446 * n nearest
1447 *
1448 * Read more about how to use read preferences [here](http://docs.mongodb.org/manual/applications/replication/#read-preference) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences).
1449 *
1450 * @param {String|ReadPreference} pref one of the listed preference options or their aliases
1451 * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference
1452 * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences
1453 * @return {Query} this
1454 * @api public
1455 */
1456
14571Query.prototype.read = function (pref) {
14580 if (arguments.length > 1 && !Query.prototype.read.deprecationWarningIssued) {
14590 console.error("Deprecation warning: 'tags' argument is not supported anymore in Query.read() method. Please use mongodb.ReadPreference object instead.");
14600 Query.prototype.read.deprecationWarningIssued = true;
1461 }
14620 this.options.readPreference = utils.readPref(pref);
14630 return this;
1464}
1465
1466/**
1467 * Sets tailable option.
1468 *
1469 * ####Example
1470 *
1471 * query.tailable() <== true
1472 * query.tailable(true)
1473 * query.tailable(false)
1474 *
1475 * ####Note
1476 *
1477 * Cannot be used with `distinct()`
1478 *
1479 * @param {Boolean} v defaults to true
1480 * @see mongodb http://www.mongodb.org/display/DOCS/Tailable+Cursors
1481 * @api public
1482 */
1483
14841Query.prototype.tailable = function () {
14850 this._validate('tailable');
1486
14870 this.options.tailable = arguments.length
1488 ? !! arguments[0]
1489 : true;
1490
14910 return this;
1492}
1493
1494/**
1495 * Merges another Query or conditions object into this one.
1496 *
1497 * When a Query is passed, conditions, field selection and options are merged.
1498 *
1499 * @param {Query|Object} source
1500 * @return {Query} this
1501 */
1502
15031Query.prototype.merge = function (source) {
15040 if (!source)
15050 return this;
1506
15070 if (!Query.canMerge(source))
15080 throw new TypeError('Invalid argument. Expected instanceof mquery or plain object');
1509
15100 if (source instanceof Query) {
1511 // if source has a feature, apply it to ourselves
1512
15130 if (source._conditions) {
15140 utils.merge(this._conditions, source._conditions);
1515 }
1516
15170 if (source._fields) {
15180 this._fields || (this._fields = {});
15190 utils.merge(this._fields, source._fields);
1520 }
1521
15220 if (source.options) {
15230 this.options || (this.options = {});
15240 utils.merge(this.options, source.options);
1525 }
1526
15270 if (source._update) {
15280 this._update || (this._update = {});
15290 utils.mergeClone(this._update, source._update);
1530 }
1531
15320 if (source._distinct) {
15330 this._distinct = source._distinct;
1534 }
1535
15360 return this;
1537 }
1538
1539 // plain object
15400 utils.merge(this._conditions, source);
1541
15420 return this;
1543}
1544
1545/**
1546 * Finds documents.
1547 *
1548 * Passing a `callback` executes the query.
1549 *
1550 * ####Example
1551 *
1552 * query.find()
1553 * query.find(callback)
1554 * query.find({ name: 'Burning Lights' }, callback)
1555 *
1556 * @param {Object} [criteria] mongodb selector
1557 * @param {Function} [callback]
1558 * @return {Query} this
1559 * @api public
1560 */
1561
15621Query.prototype.find = function (criteria, callback) {
15630 this.op = 'find';
1564
15650 if ('function' === typeof criteria) {
15660 callback = criteria;
15670 criteria = undefined;
15680 } else if (Query.canMerge(criteria)) {
15690 this.merge(criteria);
1570 }
1571
15720 if (!callback) return this;
1573
15740 var self = this
1575 , conds = this._conditions
1576 , options = this._optionsForExec()
1577
15780 options.fields = this._fieldsForExec()
1579
15800 debug('find', conds, options);
1581
15820 this._collection.find(conds, options, utils.tick(callback));
15830 return this;
1584}
1585
1586/**
1587 * Executes the query as a findOne() operation.
1588 *
1589 * Passing a `callback` executes the query.
1590 *
1591 * ####Example
1592 *
1593 * query.findOne().where('name', /^Burning/);
1594 *
1595 * query.findOne({ name: /^Burning/ })
1596 *
1597 * query.findOne({ name: /^Burning/ }, callback); // executes
1598 *
1599 * query.findOne(function (err, doc) {
1600 * if (err) return handleError(err);
1601 * if (doc) {
1602 * // doc may be null if no document matched
1603 *
1604 * }
1605 * });
1606 *
1607 * @param {Object|Query} [criteria] mongodb selector
1608 * @param {Function} [callback]
1609 * @return {Query} this
1610 * @api public
1611 */
1612
16131Query.prototype.findOne = function (criteria, callback) {
16140 this.op = 'findOne';
1615
16160 if ('function' === typeof criteria) {
16170 callback = criteria;
16180 criteria = undefined;
16190 } else if (Query.canMerge(criteria)) {
16200 this.merge(criteria);
1621 }
1622
16230 if (!callback) return this;
1624
16250 var self = this
1626 , conds = this._conditions
1627 , options = this._optionsForExec()
1628
16290 options.fields = this._fieldsForExec();
1630
16310 debug('findOne', conds, options);
16320 this._collection.findOne(conds, options, utils.tick(callback));
1633
16340 return this;
1635}
1636
1637/**
1638 * Exectues the query as a count() operation.
1639 *
1640 * Passing a `callback` executes the query.
1641 *
1642 * ####Example
1643 *
1644 * query.count().where('color', 'black').exec(callback);
1645 *
1646 * query.count({ color: 'black' }).count(callback)
1647 *
1648 * query.count({ color: 'black' }, callback)
1649 *
1650 * query.where('color', 'black').count(function (err, count) {
1651 * if (err) return handleError(err);
1652 * console.log('there are %d kittens', count);
1653 * })
1654 *
1655 * @param {Object} [criteria] mongodb selector
1656 * @param {Function} [callback]
1657 * @return {Query} this
1658 * @see mongodb http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count
1659 * @api public
1660 */
1661
16621Query.prototype.count = function (criteria, callback) {
16630 this.op = 'count';
16640 this._validate();
1665
16660 if ('function' === typeof criteria) {
16670 callback = criteria;
16680 criteria = undefined;
16690 } else if (Query.canMerge(criteria)) {
16700 this.merge(criteria);
1671 }
1672
16730 if (!callback) return this;
1674
16750 var conds = this._conditions
1676 , options = this._optionsForExec()
1677
16780 debug('count', conds, options);
16790 this._collection.count(conds, options, utils.tick(callback));
16800 return this;
1681}
1682
1683/**
1684 * Declares or executes a distict() operation.
1685 *
1686 * Passing a `callback` executes the query.
1687 *
1688 * ####Example
1689 *
1690 * distinct(criteria, field, fn)
1691 * distinct(criteria, field)
1692 * distinct(field, fn)
1693 * distinct(field)
1694 * distinct(fn)
1695 * distinct()
1696 *
1697 * @param {Object|Query} [criteria]
1698 * @param {String} [field]
1699 * @param {Function} [callback]
1700 * @return {Query} this
1701 * @see mongodb http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct
1702 * @api public
1703 */
1704
17051Query.prototype.distinct = function (criteria, field, callback) {
17060 this.op = 'distinct';
17070 this._validate();
1708
17090 if (!callback) {
17100 switch (typeof field) {
1711 case 'function':
17120 callback = field;
17130 if ('string' == typeof criteria) {
17140 field = criteria;
17150 criteria = undefined;
1716 }
17170 break;
1718 case 'undefined':
1719 case 'string':
17200 break;
1721 default:
17220 throw new TypeError('Invalid `field` argument. Must be string or function')
17230 break;
1724 }
1725
17260 switch (typeof criteria) {
1727 case 'function':
17280 callback = criteria;
17290 criteria = field = undefined;
17300 break;
1731 case 'string':
17320 field = criteria;
17330 criteria = undefined;
17340 break;
1735 }
1736 }
1737
17380 if ('string' == typeof field) {
17390 this._distinct = field;
1740 }
1741
17420 if (Query.canMerge(criteria)) {
17430 this.merge(criteria);
1744 }
1745
17460 if (!callback) {
17470 return this;
1748 }
1749
17500 if (!this._distinct) {
17510 throw new Error('No value for `distinct` has been declared');
1752 }
1753
17540 var conds = this._conditions
1755 , options = this._optionsForExec()
1756
17570 debug('distinct', conds, options);
17580 this._collection.distinct(this._distinct, conds, options, utils.tick(callback));
1759
17600 return this;
1761}
1762
1763/**
1764 * Declare and/or execute this query as an update() operation.
1765 *
1766 * _All paths passed that are not $atomic operations will become $set ops._
1767 *
1768 * ####Example
1769 *
1770 * mquery({ _id: id }).update({ title: 'words' }, ...)
1771 *
1772 * becomes
1773 *
1774 * collection.update({ _id: id }, { $set: { title: 'words' }}, ...)
1775 *
1776 * ####Note
1777 *
1778 * Passing an empty object `{}` as the doc will result in a no-op unless the `overwrite` option is passed. Without the `overwrite` option set, the update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting documents in the collection.
1779 *
1780 * ####Note
1781 *
1782 * The operation is only executed when a callback is passed. To force execution without a callback (which would be an unsafe write), we must first call update() and then execute it by using the `exec()` method.
1783 *
1784 * var q = mquery(collection).where({ _id: id });
1785 * q.update({ $set: { name: 'bob' }}).update(); // not executed
1786 *
1787 * var q = mquery(collection).where({ _id: id });
1788 * q.update({ $set: { name: 'bob' }}).exec(); // executed as unsafe
1789 *
1790 * // keys that are not $atomic ops become $set.
1791 * // this executes the same command as the previous example.
1792 * q.update({ name: 'bob' }).where({ _id: id }).exec();
1793 *
1794 * var q = mquery(collection).update(); // not executed
1795 *
1796 * // overwriting with empty docs
1797 * var q.where({ _id: id }).setOptions({ overwrite: true })
1798 * q.update({ }, callback); // executes
1799 *
1800 * // multi update with overwrite to empty doc
1801 * var q = mquery(collection).where({ _id: id });
1802 * q.setOptions({ multi: true, overwrite: true })
1803 * q.update({ });
1804 * q.update(callback); // executed
1805 *
1806 * // multi updates
1807 * mquery()
1808 * .collection(coll)
1809 * .update({ name: /^match/ }, { $set: { arr: [] }}, { multi: true }, callback)
1810 * // more multi updates
1811 * mquery({ })
1812 * .collection(coll)
1813 * .setOptions({ multi: true })
1814 * .update({ $set: { arr: [] }}, callback)
1815 *
1816 * // single update by default
1817 * mquery({ email: 'address@example.com' })
1818 * .collection(coll)
1819 * .update({ $inc: { counter: 1 }}, callback)
1820 *
1821 * // summary
1822 * update(criteria, doc, opts, cb) // executes
1823 * update(criteria, doc, opts)
1824 * update(criteria, doc, cb) // executes
1825 * update(criteria, doc)
1826 * update(doc, cb) // executes
1827 * update(doc)
1828 * update(cb) // executes
1829 * update(true) // executes (unsafe write)
1830 * update()
1831 *
1832 * @param {Object} [criteria]
1833 * @param {Object} [doc] the update command
1834 * @param {Object} [options]
1835 * @param {Function} [callback]
1836 * @return {Query} this
1837 * @api public
1838 */
1839
18401Query.prototype.update = function update (criteria, doc, options, callback) {
18410 this.op = 'update';
18420 var force;
1843
18440 switch (arguments.length) {
1845 case 3:
18460 if ('function' == typeof options) {
18470 callback = options;
18480 options = undefined;
1849 }
18500 break;
1851 case 2:
18520 if ('function' == typeof doc) {
18530 callback = doc;
18540 doc = criteria;
18550 criteria = undefined;
1856 }
18570 break;
1858 case 1:
18590 switch (typeof criteria) {
1860 case 'function':
18610 callback = criteria;
18620 criteria = options = doc = undefined;
18630 break;
1864 case 'boolean':
1865 // execution with no callback (unsafe write)
18660 force = criteria;
18670 criteria = undefined;
18680 break;
1869 default:
18700 doc = criteria;
18710 criteria = options = undefined;
18720 break;
1873 }
1874 }
1875
18760 if (Query.canMerge(criteria)) {
18770 this.merge(criteria);
1878 }
1879
18800 if (doc) {
18810 this._mergeUpdate(doc);
1882 }
1883
18840 if (utils.isObject(options)) {
1885 // { overwrite: true }
18860 this.setOptions(options);
1887 }
1888
1889 // we are done if we don't have callback and they are
1890 // not forcing an unsafe write.
18910 if (!(force || callback))
18920 return this;
1893
18940 if (!this._update ||
1895 !this.options.overwrite && 0 === utils.keys(this._update).length) {
18960 callback && utils.soon(callback.bind(null, null, 0));
18970 return this;
1898 }
1899
19000 options = this._optionsForExec();
19010 if (!callback) options.safe = false;
1902
19030 var criteria = this._conditions;
19040 doc = this._updateForExec();
1905
19060 debug('update', criteria, doc, options);
19070 this._collection.update(criteria, doc, options, utils.tick(callback));
1908
19090 return this;
1910}
1911
1912/**
1913 * Declare and/or execute this query as a remove() operation.
1914 *
1915 * ####Example
1916 *
1917 * mquery(collection).remove({ artist: 'Anne Murray' }, callback)
1918 *
1919 * ####Note
1920 *
1921 * The operation is only executed when a callback is passed. To force execution without a callback (which would be an unsafe write), we must first call remove() and then execute it by using the `exec()` method.
1922 *
1923 * // not executed
1924 * var query = mquery(collection).remove({ name: 'Anne Murray' })
1925 *
1926 * // executed
1927 * mquery(collection).remove({ name: 'Anne Murray' }, callback)
1928 * mquery(collection).remove({ name: 'Anne Murray' }).remove(callback)
1929 *
1930 * // executed without a callback (unsafe write)
1931 * query.exec()
1932 *
1933 * // summary
1934 * query.remove(conds, fn); // executes
1935 * query.remove(conds)
1936 * query.remove(fn) // executes
1937 * query.remove()
1938 *
1939 * @param {Object|Query} [criteria] mongodb selector
1940 * @param {Function} [callback]
1941 * @return {Query} this
1942 * @api public
1943 */
1944
19451Query.prototype.remove = function (criteria, callback) {
19460 this.op = 'remove';
19470 var force;
1948
19490 if ('function' === typeof criteria) {
19500 callback = criteria;
19510 criteria = undefined;
19520 } else if (Query.canMerge(criteria)) {
19530 this.merge(criteria);
19540 } else if (true === criteria) {
19550 force = criteria;
19560 criteria = undefined;
1957 }
1958
19590 if (!(force || callback))
19600 return this;
1961
19620 var options = this._optionsForExec()
19630 if (!callback) options.safe = false;
1964
19650 var conds = this._conditions;
1966
19670 debug('remove', conds, options);
19680 this._collection.remove(conds, options, utils.tick(callback));
1969
19700 return this;
1971}
1972
1973/**
1974 * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) update command.
1975 *
1976 * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed.
1977 *
1978 * ####Available options
1979 *
1980 * - `new`: bool - true to return the modified document rather than the original. defaults to true
1981 * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
1982 * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
1983 *
1984 * ####Examples
1985 *
1986 * query.findOneAndUpdate(conditions, update, options, callback) // executes
1987 * query.findOneAndUpdate(conditions, update, options) // returns Query
1988 * query.findOneAndUpdate(conditions, update, callback) // executes
1989 * query.findOneAndUpdate(conditions, update) // returns Query
1990 * query.findOneAndUpdate(update, callback) // returns Query
1991 * query.findOneAndUpdate(update) // returns Query
1992 * query.findOneAndUpdate(callback) // executes
1993 * query.findOneAndUpdate() // returns Query
1994 *
1995 * @param {Object|Query} [query]
1996 * @param {Object} [doc]
1997 * @param {Object} [options]
1998 * @param {Function} [callback]
1999 * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
2000 * @return {Query} this
2001 * @api public
2002 */
2003
20041Query.prototype.findOneAndUpdate = function (criteria, doc, options, callback) {
20050 this.op = 'findOneAndUpdate';
20060 this._validate();
2007
20080 switch (arguments.length) {
2009 case 3:
20100 if ('function' == typeof options) {
20110 callback = options;
20120 options = {};
2013 }
20140 break;
2015 case 2:
20160 if ('function' == typeof doc) {
20170 callback = doc;
20180 doc = criteria;
20190 criteria = undefined;
2020 }
20210 options = undefined;
20220 break;
2023 case 1:
20240 if ('function' == typeof criteria) {
20250 callback = criteria;
20260 criteria = options = doc = undefined;
2027 } else {
20280 doc = criteria;
20290 criteria = options = undefined;
2030 }
2031 }
2032
20330 if (Query.canMerge(criteria)) {
20340 this.merge(criteria);
2035 }
2036
2037 // apply doc
20380 if (doc) {
20390 this._mergeUpdate(doc);
2040 }
2041
20420 options && this.setOptions(options);
2043
20440 if (!callback) return this;
20450 return this._findAndModify('update', callback);
2046}
2047
2048/**
2049 * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) remove command.
2050 *
2051 * Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if `callback` is passed.
2052 *
2053 * ####Available options
2054 *
2055 * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
2056 *
2057 * ####Examples
2058 *
2059 * A.where().findOneAndRemove(conditions, options, callback) // executes
2060 * A.where().findOneAndRemove(conditions, options) // return Query
2061 * A.where().findOneAndRemove(conditions, callback) // executes
2062 * A.where().findOneAndRemove(conditions) // returns Query
2063 * A.where().findOneAndRemove(callback) // executes
2064 * A.where().findOneAndRemove() // returns Query
2065 *
2066 * @param {Object} [conditions]
2067 * @param {Object} [options]
2068 * @param {Function} [callback]
2069 * @return {Query} this
2070 * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
2071 * @api public
2072 */
2073
20741Query.prototype.findOneAndRemove = function (conditions, options, callback) {
20750 this.op = 'findOneAndRemove';
20760 this._validate();
2077
20780 if ('function' == typeof options) {
20790 callback = options;
20800 options = undefined;
20810 } else if ('function' == typeof conditions) {
20820 callback = conditions;
20830 conditions = undefined;
2084 }
2085
2086 // apply conditions
20870 if (Query.canMerge(conditions)) {
20880 this.merge(conditions);
2089 }
2090
2091 // apply options
20920 options && this.setOptions(options);
2093
20940 if (!callback) return this;
2095
20960 return this._findAndModify('remove', callback);
2097}
2098
2099/**
2100 * _findAndModify
2101 *
2102 * @param {String} type - either "remove" or "update"
2103 * @param {Function} callback
2104 * @api private
2105 */
2106
21071Query.prototype._findAndModify = function (type, callback) {
21080 assert.equal('function', typeof callback);
2109
21100 var opts = this._optionsForExec()
2111 , self = this
2112 , fields
2113 , sort
2114 , doc
2115
21160 if ('remove' == type) {
21170 opts.remove = true;
2118 } else {
21190 if (!('new' in opts)) opts.new = true;
21200 if (!('upsert' in opts)) opts.upsert = false;
2121
21220 doc = this._updateForExec()
21230 if (!doc) {
21240 if (opts.upsert) {
2125 // still need to do the upsert to empty doc
21260 doc = { $set: {} };
2127 } else {
21280 return this.findOne(callback);
2129 }
2130 }
2131 }
2132
21330 var fields = this._fieldsForExec();
21340 if (fields) {
21350 opts.fields = fields;
2136 }
2137
21380 var conds = this._conditions;
2139
21400 debug('findAndModify', conds, doc, opts);
2141
21420 this._collection
2143 .findAndModify(conds, doc, opts, utils.tick(callback));
2144
21450 return this;
2146}
2147
2148/**
2149 * Executes the query
2150 *
2151 * ####Examples
2152 *
2153 * query.exec();
2154 * query.exec(callback);
2155 * query.exec('update');
2156 * query.exec('find', callback);
2157 *
2158 * @param {String|Function} [operation]
2159 * @param {Function} [callback]
2160 * @return {Promise}
2161 * @api public
2162 */
2163
21641Query.prototype.exec = function exec (op, callback) {
21650 switch (typeof op) {
2166 case 'function':
21670 callback = op;
21680 op = null;
21690 break;
2170 case 'string':
21710 this.op = op;
21720 break;
2173 }
2174
21750 assert.ok(this.op, "Missing query type: (find, update, etc)");
2176
21770 if ('update' == this.op || 'remove' == this.op) {
21780 callback || (callback = true);
2179 }
2180
21810 this[this.op](callback);
2182}
2183
2184/**
2185 * Determines if field selection has been made.
2186 *
2187 * @return {Boolean}
2188 * @api public
2189 */
2190
21911Query.prototype.selected = function selected () {
21920 return !! (this._fields && Object.keys(this._fields).length > 0);
2193}
2194
2195/**
2196 * Determines if inclusive field selection has been made.
2197 *
2198 * query.selectedInclusively() // false
2199 * query.select('name')
2200 * query.selectedInclusively() // true
2201 * query.selectedExlusively() // false
2202 *
2203 * @returns {Boolean}
2204 */
2205
22061Query.prototype.selectedInclusively = function selectedInclusively () {
22070 if (!this._fields) return false;
2208
22090 var keys = Object.keys(this._fields);
22100 if (0 === keys.length) return false;
2211
22120 for (var i = 0; i < keys.length; ++i) {
22130 var key = keys[i];
22140 if (0 === this._fields[key]) return false;
2215 }
2216
22170 return true;
2218}
2219
2220/**
2221 * Determines if exclusive field selection has been made.
2222 *
2223 * query.selectedExlusively() // false
2224 * query.select('-name')
2225 * query.selectedExlusively() // true
2226 * query.selectedInclusively() // false
2227 *
2228 * @returns {Boolean}
2229 */
2230
22311Query.prototype.selectedExclusively = function selectedExclusively () {
22320 if (!this._fields) return false;
2233
22340 var keys = Object.keys(this._fields);
22350 if (0 === keys.length) return false;
2236
22370 for (var i = 0; i < keys.length; ++i) {
22380 var key = keys[i];
22390 if (0 === this._fields[key]) return true;
2240 }
2241
22420 return false;
2243}
2244
2245/**
2246 * Merges `doc` with the current update object.
2247 *
2248 * @param {Object} doc
2249 */
2250
22511Query.prototype._mergeUpdate = function (doc) {
22520 if (!this._update) this._update = {};
22530 if (doc instanceof Query) {
22540 if (doc._update) {
22550 utils.mergeClone(this._update, doc._update);
2256 }
2257 } else {
22580 utils.mergeClone(this._update, doc);
2259 }
2260}
2261
2262/**
2263 * Returns default options.
2264 *
2265 * @return {Object}
2266 * @api private
2267 */
2268
22691Query.prototype._optionsForExec = function () {
22700 var options = utils.clone(this.options, { retainKeyOrder: true });
22710 return options;
2272}
2273
2274/**
2275 * Returns fields selection for this query.
2276 *
2277 * @return {Object}
2278 * @api private
2279 */
2280
22811Query.prototype._fieldsForExec = function () {
22820 return utils.clone(this._fields);
2283}
2284
2285/**
2286 * Return an update document with corrected $set operations.
2287 *
2288 * @api private
2289 */
2290
22911Query.prototype._updateForExec = function () {
22920 var update = utils.clone(this._update, { retainKeyOrder: true })
2293 , ops = utils.keys(update)
2294 , i = ops.length
2295 , ret = {}
2296 , hasKeys
2297 , val
2298
22990 while (i--) {
23000 var op = ops[i];
2301
23020 if (this.options.overwrite) {
23030 ret[op] = update[op];
23040 continue;
2305 }
2306
23070 if ('$' !== op[0]) {
2308 // fix up $set sugar
23090 if (!ret.$set) {
23100 if (update.$set) {
23110 ret.$set = update.$set;
2312 } else {
23130 ret.$set = {};
2314 }
2315 }
23160 ret.$set[op] = update[op];
23170 ops.splice(i, 1);
23180 if (!~ops.indexOf('$set')) ops.push('$set');
23190 } else if ('$set' === op) {
23200 if (!ret.$set) {
23210 ret[op] = update[op];
2322 }
2323 } else {
23240 ret[op] = update[op];
2325 }
2326 }
2327
23280 return ret;
2329}
2330
2331/**
2332 * Make sure _path is set.
2333 *
2334 * @parmam {String} method
2335 */
2336
23371Query.prototype._ensurePath = function (method) {
23380 if (!this._path) {
23390 var msg = method + '() must be used after where() '
2340 + 'when called with these arguments'
23410 throw new Error(msg);
2342 }
2343}
2344
2345/*!
2346 * Permissions
2347 */
2348
23491Query.permissions = require('./permissions');
2350
23511Query._isPermitted = function (a, b) {
23520 var denied = Query.permissions[b];
23530 if (!denied) return true;
23540 return true !== denied[a];
2355}
2356
23571Query.prototype._validate = function (action) {
23580 var fail;
23590 var validator;
2360
23610 if (undefined === action) {
2362
23630 validator = Query.permissions[this.op];
23640 if ('function' != typeof validator) return true;
2365
23660 fail = validator(this);
2367
23680 } else if (!Query._isPermitted(action, this.op)) {
23690 fail = action;
2370 }
2371
23720 if (fail) {
23730 throw new Error(fail + ' cannot be used with ' + this.op);
2374 }
2375}
2376
2377/**
2378 * Determines if `conds` can be merged using `mquery().merge()`
2379 *
2380 * @param {Object} conds
2381 * @return {Boolean}
2382 */
2383
23841Query.canMerge = function (conds) {
23850 return conds instanceof Query || utils.isObject(conds);
2386}
2387
2388/*!
2389 * Exports.
2390 */
2391
23921Query.utils = utils;
23931Query.env = require('./env')
23941Query.Collection = require('./collection');
23951Query.BaseCollection = require('./collection/collection');
23961module.exports = exports = Query;
2397
2398// TODO
2399// test utils
2400

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mquery/lib/permissions.js

22%
36
8
28
LineHitsSource
11'use strict';
2
31var denied = exports;
4
51denied.distinct = function (self) {
60 if (self._fields && Object.keys(self._fields).length > 0) {
70 return 'field selection and slice'
8 }
9
100 var keys = Object.keys(denied.distinct);
110 var err;
12
130 keys.every(function (option) {
140 if (self.options[option]) {
150 err = option;
160 return false;
17 }
180 return true;
19 });
20
210 return err;
22};
231denied.distinct.select =
24denied.distinct.slice =
25denied.distinct.sort =
26denied.distinct.limit =
27denied.distinct.skip =
28denied.distinct.batchSize =
29denied.distinct.comment =
30denied.distinct.maxScan =
31denied.distinct.snapshot =
32denied.distinct.hint =
33denied.distinct.tailable = true;
34
35
36// aggregation integration
37
38
391denied.findOneAndUpdate =
40denied.findOneAndRemove = function (self) {
410 var keys = Object.keys(denied.findOneAndUpdate);
420 var err;
43
440 keys.every(function (option) {
450 if (self.options[option]) {
460 err = option;
470 return false;
48 }
490 return true;
50 });
51
520 return err;
53}
541denied.findOneAndUpdate.limit =
55denied.findOneAndUpdate.skip =
56denied.findOneAndUpdate.batchSize =
57denied.findOneAndUpdate.maxScan =
58denied.findOneAndUpdate.snapshot =
59denied.findOneAndUpdate.hint =
60denied.findOneAndUpdate.tailable =
61denied.findOneAndUpdate.comment = true;
62
63
641denied.count = function (self) {
650 if (self._fields && Object.keys(self._fields).length > 0) {
660 return 'field selection and slice'
67 }
68
690 var keys = Object.keys(denied.count);
700 var err;
71
720 keys.every(function (option) {
730 if (self.options[option]) {
740 err = option;
750 return false;
76 }
770 return true;
78 });
79
800 return err;
81}
82
831denied.count.select =
84denied.count.slice =
85denied.count.sort =
86denied.count.batchSize =
87denied.count.comment =
88denied.count.maxScan =
89denied.count.snapshot =
90denied.count.hint =
91denied.count.tailable = true;
92

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mquery/lib/utils.js

19%
104
20
84
LineHitsSource
11'use strict';
2
3/*!
4 * Module dependencies.
5 */
6
71var RegExpClone = require('regexp-clone')
8
9/**
10 * Clones objects
11 *
12 * @param {Object} obj the object to clone
13 * @param {Object} options
14 * @return {Object} the cloned object
15 * @api private
16 */
17
181var clone = exports.clone = function clone (obj, options) {
190 if (obj === undefined || obj === null)
200 return obj;
21
220 if (Array.isArray(obj))
230 return exports.cloneArray(obj, options);
24
250 if (obj.constructor) {
260 if (/ObjectI[dD]$/.test(obj.constructor.name)) {
270 return 'function' == typeof obj.clone
28 ? obj.clone()
29 : new obj.constructor(obj.id);
30 }
31
320 if ('ReadPreference' === obj._type && obj.isValid && obj.toObject) {
330 return 'function' == typeof obj.clone
34 ? obj.clone()
35 : new obj.constructor(obj.mode, clone(obj.tags, options));
36 }
37
380 if ('Binary' == obj._bsontype && obj.buffer && obj.value) {
390 return 'function' == typeof obj.clone
40 ? obj.clone()
41 : new obj.constructor(obj.value(true), obj.sub_type);
42 }
43
440 if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
450 return new obj.constructor(+obj);
46
470 if ('RegExp' === obj.constructor.name)
480 return RegExpClone(obj);
49 }
50
510 if (isObject(obj))
520 return exports.cloneObject(obj, options);
53
540 if (obj.valueOf)
550 return obj.valueOf();
56};
57
58/*!
59 * ignore
60 */
61
621var cloneObject = exports.cloneObject = function cloneObject (obj, options) {
630 var retainKeyOrder = options && options.retainKeyOrder
64 , minimize = options && options.minimize
65 , ret = {}
66 , hasKeys
67 , keys
68 , val
69 , k
70 , i
71
720 if (retainKeyOrder) {
730 for (k in obj) {
740 val = clone(obj[k], options);
75
760 if (!minimize || ('undefined' !== typeof val)) {
770 hasKeys || (hasKeys = true);
780 ret[k] = val;
79 }
80 }
81 } else {
82 // faster
83
840 keys = Object.keys(obj);
850 i = keys.length;
86
870 while (i--) {
880 k = keys[i];
890 val = clone(obj[k], options);
90
910 if (!minimize || ('undefined' !== typeof val)) {
920 if (!hasKeys) hasKeys = true;
930 ret[k] = val;
94 }
95 }
96 }
97
980 return minimize
99 ? hasKeys && ret
100 : ret;
101};
102
1031var cloneArray = exports.cloneArray = function cloneArray (arr, options) {
1040 var ret = [];
1050 for (var i = 0, l = arr.length; i < l; i++)
1060 ret.push(clone(arr[i], options));
1070 return ret;
108};
109
110/**
111 * process.nextTick helper.
112 *
113 * Wraps the given `callback` in a try/catch. If an error is
114 * caught it will be thrown on nextTick.
115 *
116 * node-mongodb-native had a habit of state corruption when
117 * an error was immediately thrown from within a collection
118 * method (find, update, etc) callback.
119 *
120 * @param {Function} [callback]
121 * @api private
122 */
123
1241var tick = exports.tick = function tick (callback) {
1250 if ('function' !== typeof callback) return;
1260 return function () {
127 // callbacks should always be fired on the next
128 // turn of the event loop. A side benefit is
129 // errors thrown from executing the callback
130 // will not cause drivers state to be corrupted
131 // which has historically been a problem.
1320 var args = arguments;
1330 soon(function(){
1340 callback.apply(this, args);
135 });
136 }
137}
138
139/**
140 * Merges `from` into `to` without overwriting existing properties.
141 *
142 * @param {Object} to
143 * @param {Object} from
144 * @api private
145 */
146
1471var merge = exports.merge = function merge (to, from) {
1480 var keys = Object.keys(from)
149 , i = keys.length
150 , key
151
1520 while (i--) {
1530 key = keys[i];
1540 if ('undefined' === typeof to[key]) {
1550 to[key] = from[key];
156 } else {
1570 if (exports.isObject(from[key])) {
1580 merge(to[key], from[key]);
159 } else {
1600 to[key] = from[key];
161 }
162 }
163 }
164}
165
166/**
167 * Same as merge but clones the assigned values.
168 *
169 * @param {Object} to
170 * @param {Object} from
171 * @api private
172 */
173
1741var mergeClone = exports.mergeClone = function mergeClone (to, from) {
1750 var keys = Object.keys(from)
176 , i = keys.length
177 , key
178
1790 while (i--) {
1800 key = keys[i];
1810 if ('undefined' === typeof to[key]) {
182 // make sure to retain key order here because of a bug handling the $each
183 // operator in mongodb 2.4.4
1840 to[key] = clone(from[key], { retainKeyOrder : 1});
185 } else {
1860 if (exports.isObject(from[key])) {
1870 mergeClone(to[key], from[key]);
188 } else {
189 // make sure to retain key order here because of a bug handling the
190 // $each operator in mongodb 2.4.4
1910 to[key] = clone(from[key], { retainKeyOrder : 1});
192 }
193 }
194 }
195}
196
197/**
198 * Read pref helper (mongo 2.2 drivers support this)
199 *
200 * Allows using aliases instead of full preference names:
201 *
202 * p primary
203 * pp primaryPreferred
204 * s secondary
205 * sp secondaryPreferred
206 * n nearest
207 *
208 * @param {String} pref
209 */
210
2111exports.readPref = function readPref (pref) {
2120 switch (pref) {
213 case 'p':
2140 pref = 'primary';
2150 break;
216 case 'pp':
2170 pref = 'primaryPreferred';
2180 break;
219 case 's':
2200 pref = 'secondary';
2210 break;
222 case 'sp':
2230 pref = 'secondaryPreferred';
2240 break;
225 case 'n':
2260 pref = 'nearest';
2270 break;
228 }
229
2300 return pref;
231}
232
233/**
234 * Object.prototype.toString.call helper
235 */
236
2371var _toString = Object.prototype.toString;
2381var toString = exports.toString = function (arg) {
2390 return _toString.call(arg);
240}
241
242/**
243 * Determines if `arg` is an object.
244 *
245 * @param {Object|Array|String|Function|RegExp|any} arg
246 * @return {Boolean}
247 */
248
2491var isObject = exports.isObject = function (arg) {
2500 return '[object Object]' == exports.toString(arg);
251}
252
253/**
254 * Determines if `arg` is an array.
255 *
256 * @param {Object}
257 * @return {Boolean}
258 * @see nodejs utils
259 */
260
2611var isArray = exports.isArray = function (arg) {
2620 return Array.isArray(arg) ||
263 'object' == typeof arg && '[object Array]' == exports.toString(arg);
264}
265
266/**
267 * Object.keys helper
268 */
269
2701exports.keys = Object.keys || function (obj) {
2710 var keys = [];
2720 for (var k in obj) if (obj.hasOwnProperty(k)) {
2730 keys.push(k);
274 }
2750 return keys;
276}
277
278/**
279 * Basic Object.create polyfill.
280 * Only one argument is supported.
281 *
282 * Based on https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create
283 */
284
2851exports.create = 'function' == typeof Object.create
286 ? Object.create
287 : create;
288
2891function create (proto) {
2900 if (arguments.length > 1) {
2910 throw new Error("Adding properties is not supported")
292 }
293
2940 function F () {}
2950 F.prototype = proto;
2960 return new F;
297}
298
299/**
300 * inheritance
301 */
302
3031exports.inherits = function (ctor, superCtor) {
3041 ctor.prototype = exports.create(superCtor.prototype);
3051 ctor.prototype.constructor = ctor;
306}
307
308/**
309 * nextTick helper
310 * compat with node 0.10 which behaves differently than previous versions
311 */
312
3131var soon = exports.soon = 'function' == typeof setImmediate
314 ? setImmediate
315 : process.nextTick;
316
317

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/mquery/node_modules/debug/lib/debug.js

47%
46
22
24
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var tty = require('tty');
6
7/**
8 * Expose `debug()` as the module.
9 */
10
111module.exports = debug;
12
13/**
14 * Enabled debuggers.
15 */
16
171var names = []
18 , skips = [];
19
201(process.env.DEBUG || '')
21 .split(/[\s,]+/)
22 .forEach(function(name){
231 name = name.replace('*', '.*?');
241 if (name[0] === '-') {
250 skips.push(new RegExp('^' + name.substr(1) + '$'));
26 } else {
271 names.push(new RegExp('^' + name + '$'));
28 }
29 });
30
31/**
32 * Colors.
33 */
34
351var colors = [6, 2, 3, 4, 5, 1];
36
37/**
38 * Previous debug() call.
39 */
40
411var prev = {};
42
43/**
44 * Previously assigned color.
45 */
46
471var prevColor = 0;
48
49/**
50 * Is stdout a TTY? Colored output is disabled when `true`.
51 */
52
531var isatty = tty.isatty(2);
54
55/**
56 * Select a color.
57 *
58 * @return {Number}
59 * @api private
60 */
61
621function color() {
630 return colors[prevColor++ % colors.length];
64}
65
66/**
67 * Humanize the given `ms`.
68 *
69 * @param {Number} m
70 * @return {String}
71 * @api private
72 */
73
741function humanize(ms) {
750 var sec = 1000
76 , min = 60 * 1000
77 , hour = 60 * min;
78
790 if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
800 if (ms >= min) return (ms / min).toFixed(1) + 'm';
810 if (ms >= sec) return (ms / sec | 0) + 's';
820 return ms + 'ms';
83}
84
85/**
86 * Create a debugger with the given `name`.
87 *
88 * @param {String} name
89 * @return {Type}
90 * @api public
91 */
92
931function debug(name) {
941 function disabled(){}
951 disabled.enabled = false;
96
971 var match = skips.some(function(re){
980 return re.test(name);
99 });
100
1011 if (match) return disabled;
102
1031 match = names.some(function(re){
1041 return re.test(name);
105 });
106
1072 if (!match) return disabled;
1080 var c = color();
109
1100 function colored(fmt) {
1110 fmt = coerce(fmt);
112
1130 var curr = new Date;
1140 var ms = curr - (prev[name] || curr);
1150 prev[name] = curr;
116
1170 fmt = ' \u001b[9' + c + 'm' + name + ' '
118 + '\u001b[3' + c + 'm\u001b[90m'
119 + fmt + '\u001b[3' + c + 'm'
120 + ' +' + humanize(ms) + '\u001b[0m';
121
1220 console.error.apply(this, arguments);
123 }
124
1250 function plain(fmt) {
1260 fmt = coerce(fmt);
127
1280 fmt = new Date().toUTCString()
129 + ' ' + name + ' ' + fmt;
1300 console.error.apply(this, arguments);
131 }
132
1330 colored.enabled = plain.enabled = true;
134
1350 return isatty || process.env.DEBUG_COLORS
136 ? colored
137 : plain;
138}
139
140/**
141 * Coerce `val`.
142 */
143
1441function coerce(val) {
1450 if (val instanceof Error) return val.stack || val.message;
1460 return val;
147}
148

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/muri/lib/index.js

44%
107
48
59
LineHitsSource
1// muri
2
3/**
4 * MongoDB URI parser as described here:
5 * http://www.mongodb.org/display/DOCS/Connections
6 */
7
8/**
9 * Module dependencies
10 */
11
121var qs = require('querystring');
13
14/**
15 * Defaults
16 */
17
181const DEFAULT_PORT = 27017;
191const DEFAULT_DB = 'test';
201const ADMIN_DB = 'admin';
21
22/**
23 * Muri
24 */
25
261module.exports = exports = function muri (str) {
271 if (!/^mongodb:\/\//.test(str)) {
280 throw new Error('Invalid mongodb uri. Must begin with "mongodb://"'
29 + '\n Received: ' + str);
30 }
31
321 var ret = {
33 hosts: []
34 , db: DEFAULT_DB
35 , options: {}
36 }
37
381 var match = /^mongodb:\/\/([^?]+)(\??.*)$/.exec(str);
391 if (!match || '/' == match[1]) {
400 throw new Error('Invalid mongodb uri. Missing hostname');
41 }
42
431 var uris = match[1];
441 var path = match[2];
451 var db;
46
471 uris.split(',').forEach(function (uri) {
481 var o = parse(uri);
49
501 if (o.host) {
511 ret.hosts.push({
52 host: o.host
53 , port: parseInt(o.port, 10)
54 })
55
561 if (!db && o.db) {
570 db = o.db;
58 }
590 } else if (o.ipc) {
600 ret.hosts.push({ ipc: o.ipc });
61 }
62
631 if (o.auth) {
640 ret.auth = {
65 user: o.auth.user
66 , pass: o.auth.pass
67 }
68 }
69 })
70
711 if (!ret.hosts.length) {
720 throw new Error('Invalid mongodb uri. Missing hostname');
73 }
74
751 var parts = path.split('?');
76
771 if (!db) {
781 if (parts[0]) {
790 db = parts[0].replace(/^\//, '');
80 } else {
81 // deal with ipc formats
821 db = /\/([^\.]+)$/.exec(match[1]);
831 if (db && db[1]) {
840 db = db[1];
85 }
86 }
87 }
88
891 if (db) {
900 ret.db = db;
911 } else if (ret.auth) {
920 ret.db = ADMIN_DB;
93 }
94
951 if (parts[1]) {
960 ret.options = options(parts[1]);
97 }
98
991 return ret;
100}
101
102/**
103 * Parse str into key/val pairs casting values appropriately.
104 */
105
1061function options (str) {
1070 var sep = /;/.test(str)
108 ? ';'
109 : '&';
110
1110 var ret = qs.parse(str, sep);
112
1130 Object.keys(ret).forEach(function (key) {
1140 var val = ret[key];
1150 if ('readPreferenceTags' == key) {
1160 val = readPref(val);
1170 if (val) {
1180 ret[key] = Array.isArray(val)
119 ? val
120 : [val];
121 }
122 } else {
1230 ret[key] = format(val);
124 }
125 });
126
1270 return ret;
128}
129
1301function format (val) {
1310 var num;
132
1330 if ('true' == val) {
1340 return true;
1350 } else if ('false' == val) {
1360 return false;
137 } else {
1380 num = parseInt(val, 10);
1390 if (!isNaN(num)) {
1400 return num;
141 }
142 }
143
1440 return val;
145}
146
1471function readPref (val) {
1480 var ret;
149
1500 if (Array.isArray(val)) {
1510 ret = val.map(readPref).filter(Boolean);
1520 return ret.length
153 ? ret
154 : undefined
155 }
156
1570 var pair = val.split(',');
1580 var hasKeys;
1590 ret = {};
160
1610 pair.forEach(function (kv) {
1620 kv = (kv || '').trim();
1630 if (!kv) return;
1640 hasKeys = true;
1650 var split = kv.split(':');
1660 ret[split[0]] = format(split[1]);
167 });
168
1690 return hasKeys && ret;
170}
171
1721var ipcRgx = /\.sock/;
173
1741function parse (uriString) {
175 // do not use require('url').parse b/c it can't handle # in username or pwd
176 // mongo uris are strange
177
1781 var uri = uriString;
1791 var ret = {};
1801 var parts;
1811 var auth;
1821 var ipcs;
183
184 // skip protocol
1851 uri = uri.replace(/^mongodb:\/\//, '');
186
187 // auth
1881 if (/@/.test(uri)) {
1890 parts = uri.split(/@/);
1900 auth = parts[0];
1910 uri = parts[1];
192
1930 parts = auth.split(':');
1940 ret.auth = {};
1950 ret.auth.user = parts[0];
1960 ret.auth.pass = parts[1];
197 }
198
199 // unix domain sockets
2001 if (ipcRgx.test(uri)) {
2010 ipcs = uri.split(ipcRgx);
2020 ret.ipc = ipcs[0] + '.sock';
203
204 // included a database?
2050 if (ipcs[1]) {
206 // strip leading / from database name
2070 ipcs[1] = ipcs[1].replace(/^\//, '');
208
2090 if (ipcs[1]) {
2100 ret.db = ipcs[1];
211 }
212 }
213
2140 return ret;
215 }
216
217 // database name
2181 parts = uri.split('/');
2191 if (parts[1]) ret.db = parts[1];
220
221 // host:port
2221 parts = parts[0].split(':');
2231 ret.host = parts[0];
2241 ret.port = parts[1] || DEFAULT_PORT;
225
2261 return ret;
227}
228
229/**
230 * Version
231 */
232
2331module.exports.version = JSON.parse(
234 require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
235).version;
236

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/mongoose/node_modules/sliced/lib/sliced.js

90%
10
9
1
LineHitsSource
1
2/**
3 * An Array.prototype.slice.call(arguments) alternative
4 *
5 * @param {Object} args something with a length
6 * @param {Number} slice
7 * @param {Number} sliceEnd
8 * @api public
9 */
10
111module.exports = function (args, slice, sliceEnd) {
121 var ret = [];
131 var len = args.length;
14
151 if (0 === len) return ret;
16
171 var start = slice < 0
18 ? Math.max(0, slice + len)
19 : slice || 0;
20
211 if (sliceEnd !== undefined) {
220 len = sliceEnd < 0
23 ? sliceEnd + len
24 : sliceEnd
25 }
26
271 while (len-- > start) {
284 ret[len - start] = args[len];
29 }
30
311 return ret;
32}
33
34

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/nconf/lib/nconf.js

91%
12
11
1
LineHitsSource
1/*
2 * nconf.js: Top-level include for the nconf module
3 *
4 * (C) 2011, Nodejitsu Inc.
5 *
6 */
7
81var fs = require('fs'),
9 async = require('async'),
10 common = require('./nconf/common'),
11 Provider = require('./nconf/provider').Provider,
12 nconf = module.exports = new Provider();
13
14//
15// Expose the version from the package.json
16//
171nconf.version = require('../package.json').version;
18
19//
20// Setup all stores as lazy-loaded getters.
21//
221fs.readdirSync(__dirname + '/nconf/stores').forEach(function (file) {
235 var store = file.replace('.js', ''),
24 name = common.capitalize(store);
25
265 nconf.__defineGetter__(name, function () {
270 return require('./nconf/stores/' + store)[name];
28 });
29});
30
31//
32// Expose the various components included with nconf
33//
341nconf.key = common.key;
351nconf.path = common.path;
361nconf.loadFiles = common.loadFiles;
371nconf.loadFilesSync = common.loadFilesSync;
381nconf.formats = require('./nconf/formats');
391nconf.Provider = Provider;
40
41

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/nconf/lib/nconf/common.js

29%
31
9
22
LineHitsSource
1/*
2 * utils.js: Utility functions for the nconf module.
3 *
4 * (C) 2011, Nodejitsu Inc.
5 *
6 */
7
81var fs = require('fs'),
9 async = require('async'),
10 formats = require('./formats'),
11 Memory = require('./stores/memory').Memory;
12
131var common = exports;
14
15//
16// ### function path (key)
17// #### @key {string} The ':' delimited key to split
18// Returns a fully-qualified path to a nested nconf key.
19// If given null or undefined it should return an empty path.
20// '' should still be respected as a path.
21//
221common.path = function (key) {
230 return key == null ? [] : key.split(':');
24};
25
26//
27// ### function key (arguments)
28// Returns a `:` joined string from the `arguments`.
29//
301common.key = function () {
310 return Array.prototype.slice.call(arguments).join(':');
32};
33
34//
35// ### function loadFiles (files, callback)
36// #### @files {Object|Array} List of files (or settings object) to load.
37// #### @callback {function} Continuation to respond to when complete.
38// Loads all the data in the specified `files`.
39//
401common.loadFiles = function (files, callback) {
410 if (!files) {
420 return callback(null, {});
43 }
44
450 var options = Array.isArray(files) ? { files: files } : files;
46
47 //
48 // Set the default JSON format if not already
49 // specified
50 //
510 options.format = options.format || formats.json;
52
530 function parseFile (file, next) {
540 fs.readFile(file, function (err, data) {
550 return !err
56 ? next(null, options.format.parse(data.toString()))
57 : next(err);
58 });
59 }
60
610 async.map(options.files, parseFile, function (err, objs) {
620 return err ? callback(err) : callback(null, common.merge(objs));
63 });
64};
65
66//
67// ### function loadFilesSync (files)
68// #### @files {Object|Array} List of files (or settings object) to load.
69// Loads all the data in the specified `files` synchronously.
70//
711common.loadFilesSync = function (files) {
720 if (!files) {
730 return;
74 }
75
76 //
77 // Set the default JSON format if not already
78 // specified
79 //
800 var options = Array.isArray(files) ? { files: files } : files;
810 options.format = options.format || formats.json;
82
830 return common.merge(options.files.map(function (file) {
840 return options.format.parse(fs.readFileSync(file, 'utf8'));
85 }));
86};
87
88//
89// ### function merge (objs)
90// #### @objs {Array} Array of object literals to merge
91// Merges the specified `objs` using a temporary instance
92// of `stores.Memory`.
93//
941common.merge = function (objs) {
950 var store = new Memory();
96
970 objs.forEach(function (obj) {
980 Object.keys(obj).forEach(function (key) {
990 store.merge(key, obj[key]);
100 });
101 });
102
1030 return store.store;
104};
105
106//
107// ### function capitalize (str)
108// #### @str {string} String to capitalize
109// Capitalizes the specified `str`.
110//
1111common.capitalize = function (str) {
1125 return str && str[0].toUpperCase() + str.slice(1);
113};
114

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/nconf/lib/nconf/formats.js

80%
5
4
1
LineHitsSource
1/*
2 * formats.js: Default formats supported by nconf
3 *
4 * (C) 2011, Nodejitsu Inc.
5 *
6 */
7
81var ini = require('ini');
9
101var formats = exports;
11
12//
13// ### @json
14// Standard JSON format which pretty prints `.stringify()`.
15//
161formats.json = {
17 stringify: function (obj, replacer, spacing) {
180 return JSON.stringify(obj, replacer || null, spacing || 2)
19 },
20 parse: JSON.parse
21};
22
23//
24// ### @ini
25// Standard INI format supplied from the `ini` module
26// http://en.wikipedia.org/wiki/INI_file
27//
281formats.ini = ini;
29

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/nconf/lib/nconf/provider.js

19%
193
38
155
LineHitsSource
1/*
2 * provider.js: Abstraction providing an interface into pluggable configuration storage.
3 *
4 * (C) 2011, Nodejitsu Inc.
5 *
6 */
7
81var async = require('async'),
9 common = require('./common');
10
11//
12// ### function Provider (options)
13// #### @options {Object} Options for this instance.
14// Constructor function for the Provider object responsible
15// for exposing the pluggable storage features of `nconf`.
16//
171var Provider = exports.Provider = function (options) {
18 //
19 // Setup default options for working with `stores`,
20 // `overrides`, `process.env` and `process.argv`.
21 //
221 options = options || {};
231 this.stores = {};
241 this.sources = [];
251 this.init(options);
26};
27
28//
29// Define wrapper functions for using basic stores
30// in this instance
31//
321['argv', 'env'].forEach(function (type) {
332 Provider.prototype[type] = function (options) {
340 return this.add(type, options);
35 };
36});
37
38//
39// ### function file (key, options)
40// #### @key {string|Object} Fully qualified options, name of file store, or path.
41// #### @path {string|Object} **Optional** Full qualified options, or path.
42// Adds a new `File` store to this instance. Accepts the following options
43//
44// nconf.file({ file: '.jitsuconf', dir: process.env.HOME, search: true });
45// nconf.file('path/to/config/file');
46// nconf.file('userconfig', 'path/to/config/file');
47// nconf.file('userconfig', { file: '.jitsuconf', search: true });
48//
491Provider.prototype.file = function (key, options) {
500 if (arguments.length == 1) {
510 options = typeof key === 'string' ? { file: key } : key;
520 key = 'file';
53 }
54 else {
550 options = typeof options === 'string'
56 ? { file: options }
57 : options;
58 }
59
600 options.type = 'file';
610 return this.add(key, options);
62};
63
64//
65// Define wrapper functions for using
66// overrides and defaults
67//
681['defaults', 'overrides'].forEach(function (type) {
692 Provider.prototype[type] = function (options) {
700 options = options || {};
710 if (!options.type) {
720 options.type = 'literal';
73 }
74
750 return this.add(type, options);
76 };
77});
78
79//
80// ### function use (name, options)
81// #### @type {string} Type of the nconf store to use.
82// #### @options {Object} Options for the store instance.
83// Adds (or replaces) a new store with the specified `name`
84// and `options`. If `options.type` is not set, then `name`
85// will be used instead:
86//
87// provider.use('file');
88// provider.use('file', { type: 'file', filename: '/path/to/userconf' })
89//
901Provider.prototype.use = function (name, options) {
910 options = options || {};
920 var type = options.type || name;
93
940 function sameOptions (store) {
950 return Object.keys(options).every(function (key) {
960 return options[key] === store[key];
97 });
98 }
99
1000 var store = this.stores[name],
101 update = store && !sameOptions(store);
102
1030 if (!store || update) {
1040 if (update) {
1050 this.remove(name);
106 }
107
1080 this.add(name, options);
109 }
110
1110 return this;
112};
113
114//
115// ### function add (name, options)
116// #### @name {string} Name of the store to add to this instance
117// #### @options {Object} Options for the store to create
118// Adds a new store with the specified `name` and `options`. If `options.type`
119// is not set, then `name` will be used instead:
120//
121// provider.add('memory');
122// provider.add('userconf', { type: 'file', filename: '/path/to/userconf' })
123//
1241Provider.prototype.add = function (name, options) {
1250 options = options || {};
1260 var type = options.type || name;
127
1280 if (!require('../nconf')[common.capitalize(type)]) {
1290 throw new Error('Cannot add store with unknown type: ' + type);
130 }
131
1320 this.stores[name] = this.create(type, options);
133
1340 if (this.stores[name].loadSync) {
1350 this.stores[name].loadSync();
136 }
137
1380 return this;
139};
140
141//
142// ### function remove (name)
143// #### @name {string} Name of the store to remove from this instance
144// Removes a store with the specified `name` from this instance. Users
145// are allowed to pass in a type argument (e.g. `memory`) as name if
146// this was used in the call to `.add()`.
147//
1481Provider.prototype.remove = function (name) {
1490 delete this.stores[name];
1500 return this;
151};
152
153//
154// ### function create (type, options)
155// #### @type {string} Type of the nconf store to use.
156// #### @options {Object} Options for the store instance.
157// Creates a store of the specified `type` using the
158// specified `options`.
159//
1601Provider.prototype.create = function (type, options) {
1610 return new (require('../nconf')[common.capitalize(type.toLowerCase())])(options);
162};
163
164//
165// ### function init (options)
166// #### @options {Object} Options to initialize this instance with.
167// Initializes this instance with additional `stores` or `sources` in the
168// `options` supplied.
169//
1701Provider.prototype.init = function (options) {
1711 var self = this;
172
173 //
174 // Add any stores passed in through the options
175 // to this instance.
176 //
1771 if (options.type) {
1780 this.add(options.type, options);
179 }
1801 else if (options.store) {
1810 this.add(options.store.name || options.store.type, options.store);
182 }
1831 else if (options.stores) {
1840 Object.keys(options.stores).forEach(function (name) {
1850 var store = options.stores[name];
1860 self.add(store.name || name || store.type, store);
187 });
188 }
189
190 //
191 // Add any read-only sources to this instance
192 //
1931 if (options.source) {
1940 this.sources.push(this.create(options.source.type || options.source.name, options.source));
195 }
1961 else if (options.sources) {
1970 Object.keys(options.sources).forEach(function (name) {
1980 var source = options.sources[name];
1990 self.sources.push(self.create(source.type || source.name || name, source));
200 });
201 }
202};
203
204//
205// ### function get (key, callback)
206// #### @key {string} Key to retrieve for this instance.
207// #### @callback {function} **Optional** Continuation to respond to when complete.
208// Retrieves the value for the specified key (if any).
209//
2101Provider.prototype.get = function (key, callback) {
211 //
212 // If there is no callback we can short-circuit into the default
213 // logic for traversing stores.
214 //
2150 if (!callback) {
2160 return this._execute('get', 1, key, callback);
217 }
218
219 //
220 // Otherwise the asynchronous, hierarchical `get` is
221 // slightly more complicated because we do not need to traverse
222 // the entire set of stores, but up until there is a defined value.
223 //
2240 var current = 0,
225 names = Object.keys(this.stores),
226 self = this,
227 response,
228 mergeObjs = [];
229
2300 async.whilst(function () {
2310 return typeof response === 'undefined' && current < names.length;
232 }, function (next) {
2330 var store = self.stores[names[current]];
2340 current++;
235
2360 if (store.get.length >= 2) {
2370 return store.get(key, function (err, value) {
2380 if (err) {
2390 return next(err);
240 }
241
2420 response = value;
243
244 // Merge objects if necessary
2450 if (typeof response === 'object' && !Array.isArray(response)) {
2460 mergeObjs.push(response);
2470 response = undefined;
248 }
249
2500 next();
251 });
252 }
253
2540 response = store.get(key);
255
256 // Merge objects if necessary
2570 if (typeof response === 'object' && !Array.isArray(response)) {
2580 mergeObjs.push(response);
2590 response = undefined;
260 }
261
2620 next();
263 }, function (err) {
2640 if (!err && mergeObjs.length) {
2650 response = common.merge(mergeObjs.reverse());
266 }
2670 return err ? callback(err) : callback(null, response);
268 });
269};
270
271//
272// ### function set (key, value, callback)
273// #### @key {string} Key to set in this instance
274// #### @value {literal|Object} Value for the specified key
275// #### @callback {function} **Optional** Continuation to respond to when complete.
276// Sets the `value` for the specified `key` in this instance.
277//
2781Provider.prototype.set = function (key, value, callback) {
2791 return this._execute('set', 2, key, value, callback);
280};
281
282//
283// ### function reset (callback)
284// #### @callback {function} **Optional** Continuation to respond to when complete.
285// Clears all keys associated with this instance.
286//
2871Provider.prototype.reset = function (callback) {
2880 return this._execute('reset', 0, callback);
289};
290
291//
292// ### function clear (key, callback)
293// #### @key {string} Key to remove from this instance
294// #### @callback {function} **Optional** Continuation to respond to when complete.
295// Removes the value for the specified `key` from this instance.
296//
2971Provider.prototype.clear = function (key, callback) {
2980 return this._execute('clear', 1, key, callback);
299};
300
301//
302// ### function merge ([key,] value [, callback])
303// #### @key {string} Key to merge the value into
304// #### @value {literal|Object} Value to merge into the key
305// #### @callback {function} **Optional** Continuation to respond to when complete.
306// Merges the properties in `value` into the existing object value at `key`.
307//
308// 1. If the existing value `key` is not an Object, it will be completely overwritten.
309// 2. If `key` is not supplied, then the `value` will be merged into the root.
310//
3111Provider.prototype.merge = function () {
3120 var self = this,
313 args = Array.prototype.slice.call(arguments),
314 callback = typeof args[args.length - 1] === 'function' && args.pop(),
315 value = args.pop(),
316 key = args.pop();
317
3180 function mergeProperty (prop, next) {
3190 return self._execute('merge', 2, prop, value[prop], next);
320 }
321
3220 if (!key) {
3230 if (Array.isArray(value) || typeof value !== 'object') {
3240 return onError(new Error('Cannot merge non-Object into top-level.'), callback);
325 }
326
3270 return async.forEach(Object.keys(value), mergeProperty, callback || function () { })
328 }
329
3300 return this._execute('merge', 2, key, value, callback);
331};
332
333//
334// ### function load (callback)
335// #### @callback {function} Continuation to respond to when complete.
336// Responds with an Object representing all keys associated in this instance.
337//
3381Provider.prototype.load = function (callback) {
3390 var self = this;
340
3410 function getStores () {
3420 var stores = Object.keys(self.stores);
3430 stores.reverse();
3440 return stores.map(function (name) {
3450 return self.stores[name];
346 });
347 }
348
3490 function loadStoreSync(store) {
3500 if (!store.loadSync) {
3510 throw new Error('nconf store ' + store.type + ' has no loadSync() method');
352 }
353
3540 return store.loadSync();
355 }
356
3570 function loadStore(store, next) {
3580 if (!store.load && !store.loadSync) {
3590 return next(new Error('nconf store ' + store.type + ' has no load() method'));
360 }
361
3620 return store.loadSync
363 ? next(null, store.loadSync())
364 : store.load(next);
365 }
366
3670 function loadBatch (targets, done) {
3680 if (!done) {
3690 return common.merge(targets.map(loadStoreSync));
370 }
371
3720 async.map(targets, loadStore, function (err, objs) {
3730 return err ? done(err) : done(null, common.merge(objs));
374 });
375 }
376
3770 function mergeSources (data) {
378 //
379 // If `data` was returned then merge it into
380 // the system store.
381 //
3820 if (data && typeof data === 'object') {
3830 self.use('sources', {
384 type: 'literal',
385 store: data
386 });
387 }
388 }
389
3900 function loadSources () {
3910 var sourceHierarchy = self.sources.splice(0);
3920 sourceHierarchy.reverse();
393
394 //
395 // If we don't have a callback and the current
396 // store is capable of loading synchronously
397 // then do so.
398 //
3990 if (!callback) {
4000 mergeSources(loadBatch(sourceHierarchy));
4010 return loadBatch(getStores());
402 }
403
4040 loadBatch(sourceHierarchy, function (err, data) {
4050 if (err) {
4060 return callback(err);
407 }
408
4090 mergeSources(data);
4100 return loadBatch(getStores(), callback);
411 });
412 }
413
4140 return self.sources.length
415 ? loadSources()
416 : loadBatch(getStores(), callback);
417};
418
419//
420// ### function save (callback)
421// #### @callback {function} **optional** Continuation to respond to when
422// complete.
423// Instructs each provider to save. If a callback is provided, we will attempt
424// asynchronous saves on the providers, falling back to synchronous saves if
425// this isn't possible. If a provider does not know how to save, it will be
426// ignored. Returns an object consisting of all of the data which was
427// actually saved.
428//
4291Provider.prototype.save = function (value, callback) {
4300 if (!callback && typeof value === 'function') {
4310 callback = value;
4320 value = null;
433 }
434
4350 var self = this,
436 names = Object.keys(this.stores);
437
4380 function saveStoreSync(memo, name) {
4390 var store = self.stores[name];
440
441 //
442 // If the `store` doesn't have a `saveSync` method,
443 // just ignore it and continue.
444 //
4450 if (store.saveSync) {
4460 var ret = store.saveSync();
4470 if (typeof ret == 'object' && ret !== null) {
4480 memo.push(ret);
449 }
450 }
4510 return memo;
452 }
453
4540 function saveStore(memo, name, next) {
4550 var store = self.stores[name];
456
457 //
458 // If the `store` doesn't have a `save` or saveSync`
459 // method(s), just ignore it and continue.
460 //
461
4620 if (store.save) {
4630 return store.save(function (err, data) {
4640 if (err) {
4650 return next(err);
466 }
467
4680 if (typeof data == 'object' && data !== null) {
4690 memo.push(data);
470 }
471
4720 next(null, memo);
473 });
474 }
4750 else if (store.saveSync) {
4760 memo.push(store.saveSync());
477 }
478
4790 next(null, memo);
480 }
481
482 //
483 // If we don't have a callback and the current
484 // store is capable of saving synchronously
485 // then do so.
486 //
4870 if (!callback) {
4880 return common.merge(names.reduce(saveStoreSync, []));
489 }
490
4910 async.reduce(names, [], saveStore, function (err, objs) {
4920 return err ? callback(err) : callback(null, common.merge(objs));
493 });
494};
495
496//
497// ### @private function _execute (action, syncLength, [arguments])
498// #### @action {string} Action to execute on `this.store`.
499// #### @syncLength {number} Function length of the sync version.
500// #### @arguments {Array} Arguments array to apply to the action
501// Executes the specified `action` on all stores for this instance, ensuring a callback supplied
502// to a synchronous store function is still invoked.
503//
5041Provider.prototype._execute = function (action, syncLength /* [arguments] */) {
5051 var args = Array.prototype.slice.call(arguments, 2),
506 callback = typeof args[args.length - 1] === 'function' && args.pop(),
507 destructive = ['set', 'clear', 'merge', 'reset'].indexOf(action) !== -1,
508 self = this,
509 response,
510 mergeObjs = [];
511
5121 function runAction (name, next) {
5130 var store = self.stores[name];
514
5150 if (destructive && store.readOnly) {
5160 return next();
517 }
518
5190 return store[action].length > syncLength
520 ? store[action].apply(store, args.concat(next))
521 : next(null, store[action].apply(store, args));
522 }
523
5241 if (callback) {
5250 return async.forEach(Object.keys(this.stores), runAction, function (err) {
5260 return err ? callback(err) : callback();
527 });
528 }
529
530
5311 Object.keys(this.stores).forEach(function (name) {
5320 if (typeof response === 'undefined') {
5330 var store = self.stores[name];
534
5350 if (destructive && store.readOnly) {
5360 return;
537 }
538
5390 response = store[action].apply(store, args);
540
541 // Merge objects if necessary
5420 if (response && action === 'get' && typeof response === 'object' && !Array.isArray(response)) {
5430 mergeObjs.push(response);
5440 response = undefined;
545 }
546 }
547 });
548
5491 if (mergeObjs.length) {
5500 response = common.merge(mergeObjs.reverse());
551 }
552
5531 return response;
554}
555
556//
557// Throw the `err` if a callback is not supplied
558//
5591function onError(err, callback) {
5600 if (callback) {
5610 return callback(err);
562 }
563
5640 throw err;
565}
566

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/nconf/lib/nconf/stores/memory.js

10%
78
8
70
LineHitsSource
1/*
2 * memory.js: Simple memory storage engine for nconf configuration(s)
3 *
4 * (C) 2011, Nodejitsu Inc.
5 *
6 */
7
81var common = require('../common');
9
10//
11// ### function Memory (options)
12// #### @options {Object} Options for this instance
13// Constructor function for the Memory nconf store which maintains
14// a nested json structure based on key delimiters `:`.
15//
16// e.g. `my:nested:key` ==> `{ my: { nested: { key: } } }`
17//
181var Memory = exports.Memory = function (options) {
190 options = options || {};
200 this.type = 'memory';
210 this.store = {};
220 this.mtimes = {};
230 this.readOnly = false;
240 this.loadFrom = options.loadFrom || null;
25
260 if (this.loadFrom) {
270 this.store = common.loadFilesSync(this.loadFrom);
28 }
29};
30
31//
32// ### function get (key)
33// #### @key {string} Key to retrieve for this instance.
34// Retrieves the value for the specified key (if any).
35//
361Memory.prototype.get = function (key) {
370 var target = this.store,
38 path = common.path(key);
39
40 //
41 // Scope into the object to get the appropriate nested context
42 //
430 while (path.length > 0) {
440 key = path.shift();
450 if (target && target.hasOwnProperty(key)) {
460 target = target[key];
470 continue;
48 }
490 return undefined;
50 }
51
520 return target;
53};
54
55//
56// ### function set (key, value)
57// #### @key {string} Key to set in this instance
58// #### @value {literal|Object} Value for the specified key
59// Sets the `value` for the specified `key` in this instance.
60//
611Memory.prototype.set = function (key, value) {
620 if (this.readOnly) {
630 return false;
64 }
65
660 var target = this.store,
67 path = common.path(key);
68
690 if (path.length === 0) {
70 //
71 // Root must be an object
72 //
730 if (!value || typeof value !== 'object') {
740 return false;
75 }
76 else {
770 this.reset();
780 this.store = value;
790 return true;
80 }
81 }
82
83 //
84 // Update the `mtime` (modified time) of the key
85 //
860 this.mtimes[key] = Date.now();
87
88 //
89 // Scope into the object to get the appropriate nested context
90 //
910 while (path.length > 1) {
920 key = path.shift();
930 if (!target[key] || typeof target[key] !== 'object') {
940 target[key] = {};
95 }
96
970 target = target[key];
98 }
99
100 // Set the specified value in the nested JSON structure
1010 key = path.shift();
1020 target[key] = value;
1030 return true;
104};
105
106//
107// ### function clear (key)
108// #### @key {string} Key to remove from this instance
109// Removes the value for the specified `key` from this instance.
110//
1111Memory.prototype.clear = function (key) {
1120 if (this.readOnly) {
1130 return false;
114 }
115
1160 var target = this.store,
117 value = target,
118 path = common.path(key);
119
120 //
121 // Remove the key from the set of `mtimes` (modified times)
122 //
1230 delete this.mtimes[key];
124
125 //
126 // Scope into the object to get the appropriate nested context
127 //
1280 for (var i = 0; i < path.length - 1; i++) {
1290 key = path[i];
1300 value = target[key];
1310 if (typeof value !== 'function' && typeof value !== 'object') {
1320 return false;
133 }
1340 target = value;
135 }
136
137 // Delete the key from the nested JSON structure
1380 key = path[i];
1390 delete target[key];
1400 return true;
141};
142
143//
144// ### function merge (key, value)
145// #### @key {string} Key to merge the value into
146// #### @value {literal|Object} Value to merge into the key
147// Merges the properties in `value` into the existing object value
148// at `key`. If the existing value `key` is not an Object, it will be
149// completely overwritten.
150//
1511Memory.prototype.merge = function (key, value) {
1520 if (this.readOnly) {
1530 return false;
154 }
155
156 //
157 // If the key is not an `Object` or is an `Array`,
158 // then simply set it. Merging is for Objects.
159 //
1600 if (typeof value !== 'object' || Array.isArray(value) || value === null) {
1610 return this.set(key, value);
162 }
163
1640 var self = this,
165 target = this.store,
166 path = common.path(key),
167 fullKey = key;
168
169 //
170 // Update the `mtime` (modified time) of the key
171 //
1720 this.mtimes[key] = Date.now();
173
174 //
175 // Scope into the object to get the appropriate nested context
176 //
1770 while (path.length > 1) {
1780 key = path.shift();
1790 if (!target[key]) {
1800 target[key] = {};
181 }
182
1830 target = target[key];
184 }
185
186 // Set the specified value in the nested JSON structure
1870 key = path.shift();
188
189 //
190 // If the current value at the key target is not an `Object`,
191 // or is an `Array` then simply override it because the new value
192 // is an Object.
193 //
1940 if (typeof target[key] !== 'object' || Array.isArray(target[key])) {
1950 target[key] = value;
1960 return true;
197 }
198
1990 return Object.keys(value).every(function (nested) {
2000 return self.merge(common.key(fullKey, nested), value[nested]);
201 });
202};
203
204//
205// ### function reset (callback)
206// Clears all keys associated with this instance.
207//
2081Memory.prototype.reset = function () {
2090 if (this.readOnly) {
2100 return false;
211 }
212
2130 this.mtimes = {};
2140 this.store = {};
2150 return true;
216};
217
218//
219// ### function loadSync
220// Returns the store managed by this instance
221//
2221Memory.prototype.loadSync = function () {
2230 return this.store || {};
224};
225

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/nconf/node_modules/async/lib/async.js

16%
534
87
447
LineHitsSource
1/*global setImmediate: false, setTimeout: false, console: false */
21(function () {
3
41 var async = {};
5
6 // global on the server, window in the browser
71 var root, previous_async;
8
91 root = this;
101 if (root != null) {
111 previous_async = root.async;
12 }
13
141 async.noConflict = function () {
150 root.async = previous_async;
160 return async;
17 };
18
191 function only_once(fn) {
200 var called = false;
210 return function() {
220 if (called) throw new Error("Callback was already called.");
230 called = true;
240 fn.apply(root, arguments);
25 }
26 }
27
28 //// cross-browser compatiblity functions ////
29
301 var _each = function (arr, iterator) {
310 if (arr.forEach) {
320 return arr.forEach(iterator);
33 }
340 for (var i = 0; i < arr.length; i += 1) {
350 iterator(arr[i], i, arr);
36 }
37 };
38
391 var _map = function (arr, iterator) {
400 if (arr.map) {
410 return arr.map(iterator);
42 }
430 var results = [];
440 _each(arr, function (x, i, a) {
450 results.push(iterator(x, i, a));
46 });
470 return results;
48 };
49
501 var _reduce = function (arr, iterator, memo) {
510 if (arr.reduce) {
520 return arr.reduce(iterator, memo);
53 }
540 _each(arr, function (x, i, a) {
550 memo = iterator(memo, x, i, a);
56 });
570 return memo;
58 };
59
601 var _keys = function (obj) {
610 if (Object.keys) {
620 return Object.keys(obj);
63 }
640 var keys = [];
650 for (var k in obj) {
660 if (obj.hasOwnProperty(k)) {
670 keys.push(k);
68 }
69 }
700 return keys;
71 };
72
73 //// exported async module functions ////
74
75 //// nextTick implementation with browser-compatible fallback ////
761 if (typeof process === 'undefined' || !(process.nextTick)) {
770 if (typeof setImmediate === 'function') {
780 async.nextTick = function (fn) {
79 // not a direct alias for IE10 compatibility
800 setImmediate(fn);
81 };
820 async.setImmediate = async.nextTick;
83 }
84 else {
850 async.nextTick = function (fn) {
860 setTimeout(fn, 0);
87 };
880 async.setImmediate = async.nextTick;
89 }
90 }
91 else {
921 async.nextTick = process.nextTick;
931 if (typeof setImmediate !== 'undefined') {
941 async.setImmediate = setImmediate;
95 }
96 else {
970 async.setImmediate = async.nextTick;
98 }
99 }
100
1011 async.each = function (arr, iterator, callback) {
1020 callback = callback || function () {};
1030 if (!arr.length) {
1040 return callback();
105 }
1060 var completed = 0;
1070 _each(arr, function (x) {
1080 iterator(x, only_once(function (err) {
1090 if (err) {
1100 callback(err);
1110 callback = function () {};
112 }
113 else {
1140 completed += 1;
1150 if (completed >= arr.length) {
1160 callback(null);
117 }
118 }
119 }));
120 });
121 };
1221 async.forEach = async.each;
123
1241 async.eachSeries = function (arr, iterator, callback) {
1250 callback = callback || function () {};
1260 if (!arr.length) {
1270 return callback();
128 }
1290 var completed = 0;
1300 var iterate = function () {
1310 iterator(arr[completed], function (err) {
1320 if (err) {
1330 callback(err);
1340 callback = function () {};
135 }
136 else {
1370 completed += 1;
1380 if (completed >= arr.length) {
1390 callback(null);
140 }
141 else {
1420 iterate();
143 }
144 }
145 });
146 };
1470 iterate();
148 };
1491 async.forEachSeries = async.eachSeries;
150
1511 async.eachLimit = function (arr, limit, iterator, callback) {
1520 var fn = _eachLimit(limit);
1530 fn.apply(null, [arr, iterator, callback]);
154 };
1551 async.forEachLimit = async.eachLimit;
156
1571 var _eachLimit = function (limit) {
158
1590 return function (arr, iterator, callback) {
1600 callback = callback || function () {};
1610 if (!arr.length || limit <= 0) {
1620 return callback();
163 }
1640 var completed = 0;
1650 var started = 0;
1660 var running = 0;
167
1680 (function replenish () {
1690 if (completed >= arr.length) {
1700 return callback();
171 }
172
1730 while (running < limit && started < arr.length) {
1740 started += 1;
1750 running += 1;
1760 iterator(arr[started - 1], function (err) {
1770 if (err) {
1780 callback(err);
1790 callback = function () {};
180 }
181 else {
1820 completed += 1;
1830 running -= 1;
1840 if (completed >= arr.length) {
1850 callback();
186 }
187 else {
1880 replenish();
189 }
190 }
191 });
192 }
193 })();
194 };
195 };
196
197
1981 var doParallel = function (fn) {
1996 return function () {
2000 var args = Array.prototype.slice.call(arguments);
2010 return fn.apply(null, [async.each].concat(args));
202 };
203 };
2041 var doParallelLimit = function(limit, fn) {
2050 return function () {
2060 var args = Array.prototype.slice.call(arguments);
2070 return fn.apply(null, [_eachLimit(limit)].concat(args));
208 };
209 };
2101 var doSeries = function (fn) {
2116 return function () {
2120 var args = Array.prototype.slice.call(arguments);
2130 return fn.apply(null, [async.eachSeries].concat(args));
214 };
215 };
216
217
2181 var _asyncMap = function (eachfn, arr, iterator, callback) {
2190 var results = [];
2200 arr = _map(arr, function (x, i) {
2210 return {index: i, value: x};
222 });
2230 eachfn(arr, function (x, callback) {
2240 iterator(x.value, function (err, v) {
2250 results[x.index] = v;
2260 callback(err);
227 });
228 }, function (err) {
2290 callback(err, results);
230 });
231 };
2321 async.map = doParallel(_asyncMap);
2331 async.mapSeries = doSeries(_asyncMap);
2341 async.mapLimit = function (arr, limit, iterator, callback) {
2350 return _mapLimit(limit)(arr, iterator, callback);
236 };
237
2381 var _mapLimit = function(limit) {
2390 return doParallelLimit(limit, _asyncMap);
240 };
241
242 // reduce only has a series version, as doing reduce in parallel won't
243 // work in many situations.
2441 async.reduce = function (arr, memo, iterator, callback) {
2450 async.eachSeries(arr, function (x, callback) {
2460 iterator(memo, x, function (err, v) {
2470 memo = v;
2480 callback(err);
249 });
250 }, function (err) {
2510 callback(err, memo);
252 });
253 };
254 // inject alias
2551 async.inject = async.reduce;
256 // foldl alias
2571 async.foldl = async.reduce;
258
2591 async.reduceRight = function (arr, memo, iterator, callback) {
2600 var reversed = _map(arr, function (x) {
2610 return x;
262 }).reverse();
2630 async.reduce(reversed, memo, iterator, callback);
264 };
265 // foldr alias
2661 async.foldr = async.reduceRight;
267
2681 var _filter = function (eachfn, arr, iterator, callback) {
2690 var results = [];
2700 arr = _map(arr, function (x, i) {
2710 return {index: i, value: x};
272 });
2730 eachfn(arr, function (x, callback) {
2740 iterator(x.value, function (v) {
2750 if (v) {
2760 results.push(x);
277 }
2780 callback();
279 });
280 }, function (err) {
2810 callback(_map(results.sort(function (a, b) {
2820 return a.index - b.index;
283 }), function (x) {
2840 return x.value;
285 }));
286 });
287 };
2881 async.filter = doParallel(_filter);
2891 async.filterSeries = doSeries(_filter);
290 // select alias
2911 async.select = async.filter;
2921 async.selectSeries = async.filterSeries;
293
2941 var _reject = function (eachfn, arr, iterator, callback) {
2950 var results = [];
2960 arr = _map(arr, function (x, i) {
2970 return {index: i, value: x};
298 });
2990 eachfn(arr, function (x, callback) {
3000 iterator(x.value, function (v) {
3010 if (!v) {
3020 results.push(x);
303 }
3040 callback();
305 });
306 }, function (err) {
3070 callback(_map(results.sort(function (a, b) {
3080 return a.index - b.index;
309 }), function (x) {
3100 return x.value;
311 }));
312 });
313 };
3141 async.reject = doParallel(_reject);
3151 async.rejectSeries = doSeries(_reject);
316
3171 var _detect = function (eachfn, arr, iterator, main_callback) {
3180 eachfn(arr, function (x, callback) {
3190 iterator(x, function (result) {
3200 if (result) {
3210 main_callback(x);
3220 main_callback = function () {};
323 }
324 else {
3250 callback();
326 }
327 });
328 }, function (err) {
3290 main_callback();
330 });
331 };
3321 async.detect = doParallel(_detect);
3331 async.detectSeries = doSeries(_detect);
334
3351 async.some = function (arr, iterator, main_callback) {
3360 async.each(arr, function (x, callback) {
3370 iterator(x, function (v) {
3380 if (v) {
3390 main_callback(true);
3400 main_callback = function () {};
341 }
3420 callback();
343 });
344 }, function (err) {
3450 main_callback(false);
346 });
347 };
348 // any alias
3491 async.any = async.some;
350
3511 async.every = function (arr, iterator, main_callback) {
3520 async.each(arr, function (x, callback) {
3530 iterator(x, function (v) {
3540 if (!v) {
3550 main_callback(false);
3560 main_callback = function () {};
357 }
3580 callback();
359 });
360 }, function (err) {
3610 main_callback(true);
362 });
363 };
364 // all alias
3651 async.all = async.every;
366
3671 async.sortBy = function (arr, iterator, callback) {
3680 async.map(arr, function (x, callback) {
3690 iterator(x, function (err, criteria) {
3700 if (err) {
3710 callback(err);
372 }
373 else {
3740 callback(null, {value: x, criteria: criteria});
375 }
376 });
377 }, function (err, results) {
3780 if (err) {
3790 return callback(err);
380 }
381 else {
3820 var fn = function (left, right) {
3830 var a = left.criteria, b = right.criteria;
3840 return a < b ? -1 : a > b ? 1 : 0;
385 };
3860 callback(null, _map(results.sort(fn), function (x) {
3870 return x.value;
388 }));
389 }
390 });
391 };
392
3931 async.auto = function (tasks, callback) {
3940 callback = callback || function () {};
3950 var keys = _keys(tasks);
3960 if (!keys.length) {
3970 return callback(null);
398 }
399
4000 var results = {};
401
4020 var listeners = [];
4030 var addListener = function (fn) {
4040 listeners.unshift(fn);
405 };
4060 var removeListener = function (fn) {
4070 for (var i = 0; i < listeners.length; i += 1) {
4080 if (listeners[i] === fn) {
4090 listeners.splice(i, 1);
4100 return;
411 }
412 }
413 };
4140 var taskComplete = function () {
4150 _each(listeners.slice(0), function (fn) {
4160 fn();
417 });
418 };
419
4200 addListener(function () {
4210 if (_keys(results).length === keys.length) {
4220 callback(null, results);
4230 callback = function () {};
424 }
425 });
426
4270 _each(keys, function (k) {
4280 var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
4290 var taskCallback = function (err) {
4300 var args = Array.prototype.slice.call(arguments, 1);
4310 if (args.length <= 1) {
4320 args = args[0];
433 }
4340 if (err) {
4350 var safeResults = {};
4360 _each(_keys(results), function(rkey) {
4370 safeResults[rkey] = results[rkey];
438 });
4390 safeResults[k] = args;
4400 callback(err, safeResults);
441 // stop subsequent errors hitting callback multiple times
4420 callback = function () {};
443 }
444 else {
4450 results[k] = args;
4460 async.setImmediate(taskComplete);
447 }
448 };
4490 var requires = task.slice(0, Math.abs(task.length - 1)) || [];
4500 var ready = function () {
4510 return _reduce(requires, function (a, x) {
4520 return (a && results.hasOwnProperty(x));
453 }, true) && !results.hasOwnProperty(k);
454 };
4550 if (ready()) {
4560 task[task.length - 1](taskCallback, results);
457 }
458 else {
4590 var listener = function () {
4600 if (ready()) {
4610 removeListener(listener);
4620 task[task.length - 1](taskCallback, results);
463 }
464 };
4650 addListener(listener);
466 }
467 });
468 };
469
4701 async.waterfall = function (tasks, callback) {
4710 callback = callback || function () {};
4720 if (tasks.constructor !== Array) {
4730 var err = new Error('First argument to waterfall must be an array of functions');
4740 return callback(err);
475 }
4760 if (!tasks.length) {
4770 return callback();
478 }
4790 var wrapIterator = function (iterator) {
4800 return function (err) {
4810 if (err) {
4820 callback.apply(null, arguments);
4830 callback = function () {};
484 }
485 else {
4860 var args = Array.prototype.slice.call(arguments, 1);
4870 var next = iterator.next();
4880 if (next) {
4890 args.push(wrapIterator(next));
490 }
491 else {
4920 args.push(callback);
493 }
4940 async.setImmediate(function () {
4950 iterator.apply(null, args);
496 });
497 }
498 };
499 };
5000 wrapIterator(async.iterator(tasks))();
501 };
502
5031 var _parallel = function(eachfn, tasks, callback) {
5040 callback = callback || function () {};
5050 if (tasks.constructor === Array) {
5060 eachfn.map(tasks, function (fn, callback) {
5070 if (fn) {
5080 fn(function (err) {
5090 var args = Array.prototype.slice.call(arguments, 1);
5100 if (args.length <= 1) {
5110 args = args[0];
512 }
5130 callback.call(null, err, args);
514 });
515 }
516 }, callback);
517 }
518 else {
5190 var results = {};
5200 eachfn.each(_keys(tasks), function (k, callback) {
5210 tasks[k](function (err) {
5220 var args = Array.prototype.slice.call(arguments, 1);
5230 if (args.length <= 1) {
5240 args = args[0];
525 }
5260 results[k] = args;
5270 callback(err);
528 });
529 }, function (err) {
5300 callback(err, results);
531 });
532 }
533 };
534
5351 async.parallel = function (tasks, callback) {
5360 _parallel({ map: async.map, each: async.each }, tasks, callback);
537 };
538
5391 async.parallelLimit = function(tasks, limit, callback) {
5400 _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
541 };
542
5431 async.series = function (tasks, callback) {
5440 callback = callback || function () {};
5450 if (tasks.constructor === Array) {
5460 async.mapSeries(tasks, function (fn, callback) {
5470 if (fn) {
5480 fn(function (err) {
5490 var args = Array.prototype.slice.call(arguments, 1);
5500 if (args.length <= 1) {
5510 args = args[0];
552 }
5530 callback.call(null, err, args);
554 });
555 }
556 }, callback);
557 }
558 else {
5590 var results = {};
5600 async.eachSeries(_keys(tasks), function (k, callback) {
5610 tasks[k](function (err) {
5620 var args = Array.prototype.slice.call(arguments, 1);
5630 if (args.length <= 1) {
5640 args = args[0];
565 }
5660 results[k] = args;
5670 callback(err);
568 });
569 }, function (err) {
5700 callback(err, results);
571 });
572 }
573 };
574
5751 async.iterator = function (tasks) {
5760 var makeCallback = function (index) {
5770 var fn = function () {
5780 if (tasks.length) {
5790 tasks[index].apply(null, arguments);
580 }
5810 return fn.next();
582 };
5830 fn.next = function () {
5840 return (index < tasks.length - 1) ? makeCallback(index + 1): null;
585 };
5860 return fn;
587 };
5880 return makeCallback(0);
589 };
590
5911 async.apply = function (fn) {
5920 var args = Array.prototype.slice.call(arguments, 1);
5930 return function () {
5940 return fn.apply(
595 null, args.concat(Array.prototype.slice.call(arguments))
596 );
597 };
598 };
599
6001 var _concat = function (eachfn, arr, fn, callback) {
6010 var r = [];
6020 eachfn(arr, function (x, cb) {
6030 fn(x, function (err, y) {
6040 r = r.concat(y || []);
6050 cb(err);
606 });
607 }, function (err) {
6080 callback(err, r);
609 });
610 };
6111 async.concat = doParallel(_concat);
6121 async.concatSeries = doSeries(_concat);
613
6141 async.whilst = function (test, iterator, callback) {
6150 if (test()) {
6160 iterator(function (err) {
6170 if (err) {
6180 return callback(err);
619 }
6200 async.whilst(test, iterator, callback);
621 });
622 }
623 else {
6240 callback();
625 }
626 };
627
6281 async.doWhilst = function (iterator, test, callback) {
6290 iterator(function (err) {
6300 if (err) {
6310 return callback(err);
632 }
6330 if (test()) {
6340 async.doWhilst(iterator, test, callback);
635 }
636 else {
6370 callback();
638 }
639 });
640 };
641
6421 async.until = function (test, iterator, callback) {
6430 if (!test()) {
6440 iterator(function (err) {
6450 if (err) {
6460 return callback(err);
647 }
6480 async.until(test, iterator, callback);
649 });
650 }
651 else {
6520 callback();
653 }
654 };
655
6561 async.doUntil = function (iterator, test, callback) {
6570 iterator(function (err) {
6580 if (err) {
6590 return callback(err);
660 }
6610 if (!test()) {
6620 async.doUntil(iterator, test, callback);
663 }
664 else {
6650 callback();
666 }
667 });
668 };
669
6701 async.queue = function (worker, concurrency) {
6710 if (concurrency === undefined) {
6720 concurrency = 1;
673 }
6740 function _insert(q, data, pos, callback) {
6750 if(data.constructor !== Array) {
6760 data = [data];
677 }
6780 _each(data, function(task) {
6790 var item = {
680 data: task,
681 callback: typeof callback === 'function' ? callback : null
682 };
683
6840 if (pos) {
6850 q.tasks.unshift(item);
686 } else {
6870 q.tasks.push(item);
688 }
689
6900 if (q.saturated && q.tasks.length === concurrency) {
6910 q.saturated();
692 }
6930 async.setImmediate(q.process);
694 });
695 }
696
6970 var workers = 0;
6980 var q = {
699 tasks: [],
700 concurrency: concurrency,
701 saturated: null,
702 empty: null,
703 drain: null,
704 push: function (data, callback) {
7050 _insert(q, data, false, callback);
706 },
707 unshift: function (data, callback) {
7080 _insert(q, data, true, callback);
709 },
710 process: function () {
7110 if (workers < q.concurrency && q.tasks.length) {
7120 var task = q.tasks.shift();
7130 if (q.empty && q.tasks.length === 0) {
7140 q.empty();
715 }
7160 workers += 1;
7170 var next = function () {
7180 workers -= 1;
7190 if (task.callback) {
7200 task.callback.apply(task, arguments);
721 }
7220 if (q.drain && q.tasks.length + workers === 0) {
7230 q.drain();
724 }
7250 q.process();
726 };
7270 var cb = only_once(next);
7280 worker(task.data, cb);
729 }
730 },
731 length: function () {
7320 return q.tasks.length;
733 },
734 running: function () {
7350 return workers;
736 }
737 };
7380 return q;
739 };
740
7411 async.cargo = function (worker, payload) {
7420 var working = false,
743 tasks = [];
744
7450 var cargo = {
746 tasks: tasks,
747 payload: payload,
748 saturated: null,
749 empty: null,
750 drain: null,
751 push: function (data, callback) {
7520 if(data.constructor !== Array) {
7530 data = [data];
754 }
7550 _each(data, function(task) {
7560 tasks.push({
757 data: task,
758 callback: typeof callback === 'function' ? callback : null
759 });
7600 if (cargo.saturated && tasks.length === payload) {
7610 cargo.saturated();
762 }
763 });
7640 async.setImmediate(cargo.process);
765 },
766 process: function process() {
7670 if (working) return;
7680 if (tasks.length === 0) {
7690 if(cargo.drain) cargo.drain();
7700 return;
771 }
772
7730 var ts = typeof payload === 'number'
774 ? tasks.splice(0, payload)
775 : tasks.splice(0);
776
7770 var ds = _map(ts, function (task) {
7780 return task.data;
779 });
780
7810 if(cargo.empty) cargo.empty();
7820 working = true;
7830 worker(ds, function () {
7840 working = false;
785
7860 var args = arguments;
7870 _each(ts, function (data) {
7880 if (data.callback) {
7890 data.callback.apply(null, args);
790 }
791 });
792
7930 process();
794 });
795 },
796 length: function () {
7970 return tasks.length;
798 },
799 running: function () {
8000 return working;
801 }
802 };
8030 return cargo;
804 };
805
8061 var _console_fn = function (name) {
8072 return function (fn) {
8080 var args = Array.prototype.slice.call(arguments, 1);
8090 fn.apply(null, args.concat([function (err) {
8100 var args = Array.prototype.slice.call(arguments, 1);
8110 if (typeof console !== 'undefined') {
8120 if (err) {
8130 if (console.error) {
8140 console.error(err);
815 }
816 }
8170 else if (console[name]) {
8180 _each(args, function (x) {
8190 console[name](x);
820 });
821 }
822 }
823 }]));
824 };
825 };
8261 async.log = _console_fn('log');
8271 async.dir = _console_fn('dir');
828 /*async.info = _console_fn('info');
829 async.warn = _console_fn('warn');
830 async.error = _console_fn('error');*/
831
8321 async.memoize = function (fn, hasher) {
8330 var memo = {};
8340 var queues = {};
8350 hasher = hasher || function (x) {
8360 return x;
837 };
8380 var memoized = function () {
8390 var args = Array.prototype.slice.call(arguments);
8400 var callback = args.pop();
8410 var key = hasher.apply(null, args);
8420 if (key in memo) {
8430 callback.apply(null, memo[key]);
844 }
8450 else if (key in queues) {
8460 queues[key].push(callback);
847 }
848 else {
8490 queues[key] = [callback];
8500 fn.apply(null, args.concat([function () {
8510 memo[key] = arguments;
8520 var q = queues[key];
8530 delete queues[key];
8540 for (var i = 0, l = q.length; i < l; i++) {
8550 q[i].apply(null, arguments);
856 }
857 }]));
858 }
859 };
8600 memoized.memo = memo;
8610 memoized.unmemoized = fn;
8620 return memoized;
863 };
864
8651 async.unmemoize = function (fn) {
8660 return function () {
8670 return (fn.unmemoized || fn).apply(null, arguments);
868 };
869 };
870
8711 async.times = function (count, iterator, callback) {
8720 var counter = [];
8730 for (var i = 0; i < count; i++) {
8740 counter.push(i);
875 }
8760 return async.map(counter, iterator, callback);
877 };
878
8791 async.timesSeries = function (count, iterator, callback) {
8800 var counter = [];
8810 for (var i = 0; i < count; i++) {
8820 counter.push(i);
883 }
8840 return async.mapSeries(counter, iterator, callback);
885 };
886
8871 async.compose = function (/* functions... */) {
8880 var fns = Array.prototype.reverse.call(arguments);
8890 return function () {
8900 var that = this;
8910 var args = Array.prototype.slice.call(arguments);
8920 var callback = args.pop();
8930 async.reduce(fns, args, function (newargs, fn, cb) {
8940 fn.apply(that, newargs.concat([function () {
8950 var err = arguments[0];
8960 var nextargs = Array.prototype.slice.call(arguments, 1);
8970 cb(err, nextargs);
898 }]))
899 },
900 function (err, results) {
9010 callback.apply(that, [err].concat(results));
902 });
903 };
904 };
905
9061 var _applyEach = function (eachfn, fns /*args...*/) {
9070 var go = function () {
9080 var that = this;
9090 var args = Array.prototype.slice.call(arguments);
9100 var callback = args.pop();
9110 return eachfn(fns, function (fn, cb) {
9120 fn.apply(that, args.concat([cb]));
913 },
914 callback);
915 };
9160 if (arguments.length > 2) {
9170 var args = Array.prototype.slice.call(arguments, 2);
9180 return go.apply(this, args);
919 }
920 else {
9210 return go;
922 }
923 };
9241 async.applyEach = doParallel(_applyEach);
9251 async.applyEachSeries = doSeries(_applyEach);
926
9271 async.forever = function (fn, callback) {
9280 function next(err) {
9290 if (err) {
9300 if (callback) {
9310 return callback(err);
932 }
9330 throw err;
934 }
9350 fn(next);
936 }
9370 next();
938 };
939
940 // AMD / RequireJS
9411 if (typeof define !== 'undefined' && define.amd) {
9420 define([], function () {
9430 return async;
944 });
945 }
946 // Node.js
9471 else if (typeof module !== 'undefined' && module.exports) {
9481 module.exports = async;
949 }
950 // included directly via <script> tag
951 else {
9520 root.async = async;
953 }
954
955}());
956

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/lib/agent.js

44%
18
8
10
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var Agent = require('superagent').agent
7 , methods = require('methods')
8 , http = require('http')
9 , Test = require('./test');
10
11/**
12 * Expose `Agent`.
13 */
14
151module.exports = TestAgent;
16
17/**
18 * Initialize a new `TestAgent`.
19 *
20 * @param {Function|Server} app
21 * @api public
22 */
23
241function TestAgent(app){
250 if (!(this instanceof TestAgent)) return new TestAgent(app);
260 if ('function' == typeof app) app = http.createServer(app);
270 Agent.call(this);
280 this.app = app;
29}
30
31/**
32 * Inherits from `Agent.prototype`.
33 */
34
351TestAgent.prototype.__proto__ = Agent.prototype;
36
37// override HTTP verb methods
38
391methods.forEach(function(method){
4024 var name = 'delete' == method ? 'del' : method;
41
4224 method = method.toUpperCase();
4324 TestAgent.prototype[name] = function(url, fn){
440 var req = new Test(this.app, method, url);
45
460 req.on('response', this.saveCookies.bind(this));
470 req.on('redirect', this.saveCookies.bind(this));
480 req.on('redirect', this.attachCookies.bind(this, req));
490 this.attachCookies(req);
50
510 return req;
52 };
53});

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/lib/test.js

11%
78
9
69
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var request = require('superagent')
7 , util = require('util')
8 , http = require('http')
9 , https = require('https')
10 , assert = require('assert')
11 , Request = request.Request;
12
13/**
14 * Expose `Test`.
15 */
16
171module.exports = Test;
18
19/**
20 * Initialize a new `Test` with the given `app`,
21 * request `method` and `path`.
22 *
23 * @param {Server} app
24 * @param {String} method
25 * @param {String} path
26 * @api public
27 */
28
291function Test(app, method, path) {
300 Request.call(this, method, path);
310 this.redirects(0);
320 this.buffer();
330 this.app = app;
340 this._fields = {};
350 this._bodies = [];
360 this.url = 'string' == typeof app
37 ? app + path
38 : this.serverAddress(app, path);
39}
40
41/**
42 * Inherits from `Request.prototype`.
43 */
44
451Test.prototype.__proto__ = Request.prototype;
46
47/**
48 * Returns a URL, extracted from a server.
49 *
50 * @param {Server} app
51 * @param {String} path
52 * @returns {String} URL address
53 * @api private
54 */
55
561Test.prototype.serverAddress = function(app, path){
570 var addr = app.address();
580 if (!addr) app.listen(0);
590 var port = app.address().port;
600 var protocol = app instanceof https.Server ? 'https' : 'http';
610 return protocol + '://127.0.0.1:' + port + path;
62};
63
64/**
65 * Expectations:
66 *
67 * .expect(200)
68 * .expect(200, fn)
69 * .expect(200, body)
70 * .expect('Some body')
71 * .expect('Some body', fn)
72 * .expect('Content-Type', 'application/json')
73 * .expect('Content-Type', 'application/json', fn)
74 *
75 * @return {Test}
76 * @api public
77 */
78
791Test.prototype.expect = function(a, b, c){
800 var self = this;
81
82 // callback
830 if ('function' == typeof b) this.end(b);
840 if ('function' == typeof c) this.end(c);
85
86 // status
870 if ('number' == typeof a) {
880 this._status = a;
89 // body
900 if ('function' != typeof b && arguments.length > 1) this._bodies.push(b);
910 return this;
92 }
93
94 // header field
950 if ('string' == typeof b || b instanceof RegExp) {
960 if (!this._fields[a]) this._fields[a] = [];
970 this._fields[a].push(b);
980 return this;
99 }
100
101 // body
1020 this._bodies.push(a);
103
1040 return this;
105};
106
107/**
108 * Defer invoking superagent's `.end()` until
109 * the server is listening.
110 *
111 * @param {Function} fn
112 * @api public
113 */
114
1151Test.prototype.end = function(fn){
1160 var self = this;
1170 var end = Request.prototype.end;
1180 end.call(this, function(err, res){
1190 if (err) return fn(err);
1200 self.assert(res, fn);
121 });
1220 return this;
123};
124
125/**
126 * Perform assertions and invoke `fn(err)`.
127 *
128 * @param {Response} res
129 * @param {Function} fn
130 * @api private
131 */
132
1331Test.prototype.assert = function(res, fn){
1340 var status = this._status
135 , fields = this._fields
136 , bodies = this._bodies
137 , expecteds
138 , actual
139 , re;
140
141 // status
1420 if (status && res.status !== status) {
1430 var a = http.STATUS_CODES[status];
1440 var b = http.STATUS_CODES[res.status];
1450 return fn(new Error('expected ' + status + ' "' + a + '", got ' + res.status + ' "' + b + '"'), res);
146 }
147
148 // body
1490 for (var i = 0; i < bodies.length; i++) {
1500 var body = bodies[i];
1510 var isregexp = body instanceof RegExp;
152 // parsed
1530 if ('object' == typeof body && !isregexp) {
1540 try {
1550 assert.deepEqual(body, res.body);
156 } catch (err) {
1570 var a = util.inspect(body);
1580 var b = util.inspect(res.body);
1590 return fn(error('expected ' + a + ' response body, got ' + b, body, res.body));
160 }
161 } else {
162 // string
1630 if (body !== res.text) {
1640 var a = util.inspect(body);
1650 var b = util.inspect(res.text);
166
167 // regexp
1680 if (isregexp) {
1690 if (!body.test(res.text)) {
1700 return fn(error('expected body ' + b + ' to match ' + body, body, res.body));
171 }
172 } else {
1730 return fn(error('expected ' + a + ' response body, got ' + b, body, res.body));
174 }
175 }
176 }
177 }
178
179 // fields
1800 for (var field in fields) {
1810 expecteds = fields[field];
1820 actual = res.header[field.toLowerCase()];
1830 if (null == actual) return fn(new Error('expected "' + field + '" header field'));
1840 for (var i = 0; i < expecteds.length; i++) {
1850 var fieldExpected = expecteds[i];
1860 if (fieldExpected == actual) continue;
1870 if (fieldExpected instanceof RegExp) re = fieldExpected;
1880 if (re && re.test(actual)) continue;
1890 if (re) return fn(new Error('expected "' + field + '" matching ' + fieldExpected + ', got "' + actual + '"'));
1900 return fn(new Error('expected "' + field + '" of "' + fieldExpected + '", got "' + actual + '"'));
191 }
192 }
193
1940 fn.call(this, null, res);
195};
196
197/**
198 * Return an `Error` with `msg` and results properties.
199 *
200 * @param {String} msg
201 * @param {Mixed} expected
202 * @param {Mixed} actual
203 * @return {Error}
204 * @api private
205 */
206
2071function error(msg, expected, actual) {
2080 var err = new Error(msg);
2090 err.expected = expected;
2100 err.actual = actual;
2110 err.showDiff = true;
2120 return err;
213}
214
215

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/lib/node/agent.js

46%
28
13
15
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var CookieJar = require('cookiejar').CookieJar;
71var CookieAccess = require('cookiejar').CookieAccessInfo;
81var parse = require('url').parse;
91var request = require('./index');
101var methods = require('methods');
11
12/**
13 * Expose `Agent`.
14 */
15
161module.exports = Agent;
17
18/**
19 * Initialize a new `Agent`.
20 *
21 * @api public
22 */
23
241function Agent() {
250 if (!(this instanceof Agent)) return new Agent;
260 this.jar = new CookieJar;
27}
28
29/**
30 * Save the cookies in the given `res` to
31 * the agent's cookie jar for persistence.
32 *
33 * @param {Response} res
34 * @api private
35 */
36
371Agent.prototype.saveCookies = function(res){
380 var cookies = res.headers['set-cookie'];
390 if (cookies) this.jar.setCookies(cookies);
40};
41
42/**
43 * Attach cookies when available to the given `req`.
44 *
45 * @param {Request} req
46 * @api private
47 */
48
491Agent.prototype.attachCookies = function(req){
500 var url = parse(req.url);
510 var access = CookieAccess(url.host, url.pathname, 'https:' == url.protocol);
520 var cookies = this.jar.getCookies(access).toValueString();
530 req.cookies = cookies;
54};
55
56// generate HTTP verb methods
57
581methods.forEach(function(method){
5923 var name = 'delete' == method ? 'del' : method;
60
6123 method = method.toUpperCase();
6223 Agent.prototype[name] = function(url, fn){
630 var req = request(method, url);
64
650 req.on('response', this.saveCookies.bind(this));
660 req.on('redirect', this.saveCookies.bind(this));
670 req.on('redirect', this.attachCookies.bind(this, req));
680 this.attachCookies(req);
69
700 fn && req.end(fn);
710 return req;
72 };
73});
74

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/lib/node/index.js

19%
320
62
258
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var debug = require('debug')('superagent');
71var formidable = require('formidable');
81var Response = require('./response');
91var parse = require('url').parse;
101var format = require('url').format;
111var methods = require('methods');
121var Stream = require('stream');
131var utils = require('./utils');
141var Part = require('./part');
151var mime = require('mime');
161var https = require('https');
171var http = require('http');
181var fs = require('fs');
191var qs = require('qs');
201var zlib = require('zlib');
211var util = require('util');
22
23/**
24 * Expose the request function.
25 */
26
271exports = module.exports = request;
28
29/**
30 * Expose the agent function
31 */
32
331exports.agent = require('./agent');
34
35
36/**
37 * Expose `Part`.
38 */
39
401exports.Part = Part;
41
42/**
43 * Noop.
44 */
45
461function noop(){};
47
48/**
49 * Expose `Response`.
50 */
51
521exports.Response = Response;
53
54/**
55 * Define "form" mime type.
56 */
57
581mime.define({
59 'application/x-www-form-urlencoded': ['form', 'urlencoded', 'form-data']
60});
61
62/**
63 * Protocol map.
64 */
65
661exports.protocols = {
67 'http:': http,
68 'https:': https
69};
70
71/**
72 * Check if `obj` is an object.
73 *
74 * @param {Object} obj
75 * @return {Boolean}
76 * @api private
77 */
78
791function isObject(obj) {
800 return null != obj && 'object' == typeof obj;
81}
82
83/**
84 * Default serialization map.
85 *
86 * superagent.serialize['application/xml'] = function(obj){
87 * return 'generated xml here';
88 * };
89 *
90 */
91
921exports.serialize = {
93 'application/x-www-form-urlencoded': qs.stringify,
94 'application/json': JSON.stringify
95};
96
97/**
98 * Default parsers.
99 *
100 * superagent.parse['application/xml'] = function(res, fn){
101 * fn(null, result);
102 * };
103 *
104 */
105
1061exports.parse = require('./parsers');
107
108/**
109 * Initialize a new `Request` with the given `method` and `url`.
110 *
111 * @param {String} method
112 * @param {String|Object} url
113 * @api public
114 */
115
1161function Request(method, url) {
1170 var self = this;
1180 if ('string' != typeof url) url = format(url);
1190 this._agent = false;
1200 this.method = method;
1210 this.url = url;
1220 this.header = {};
1230 this.writable = true;
1240 this._redirects = 0;
1250 this.redirects(5);
1260 this.attachments = [];
1270 this.cookies = '';
1280 this._redirectList = [];
1290 this.on('end', this.clearTimeout.bind(this));
1300 this.on('response', function(res){
1310 self.callback(null, res);
132 });
133}
134
135/**
136 * Inherit from `Stream.prototype`.
137 */
138
1391Request.prototype.__proto__ = Stream.prototype;
140
141/**
142 * Queue the given `file` as an attachment
143 * with optional `filename`.
144 *
145 * @param {String} field
146 * @param {String} file
147 * @param {String} filename
148 * @return {Request} for chaining
149 * @api public
150 */
151
1521Request.prototype.attach = function(field, file, filename){
1530 debug('attach %s %s', field, file);
1540 this.attachments.push({
155 field: field,
156 path: file,
157 part: new Part(this),
158 filename: filename || file
159 });
1600 return this;
161};
162
163/**
164 * Set the max redirects to `n`.
165 *
166 * @param {Number} n
167 * @return {Request} for chaining
168 * @api public
169 */
170
1711Request.prototype.redirects = function(n){
1720 debug('max redirects %s', n);
1730 this._maxRedirects = n;
1740 return this;
175};
176
177/**
178 * Return a new `Part` for this request.
179 *
180 * @return {Part}
181 * @api public
182 */
183
1841Request.prototype.part = function(){
1850 return new Part(this);
186};
187
188/**
189 * Gets/sets the `Agent` to use for this HTTP request. The default (if this
190 * function is not called) is to opt out of connection pooling (`agent: false`).
191 *
192 * @param {http.Agent} agent
193 * @return {http.Agent}
194 * @api public
195 */
196
1971Request.prototype.agent = function(agent){
1980 if (agent) this._agent = agent;
1990 return this._agent;
200};
201
202/**
203 * Set header `field` to `val`, or multiple fields with one object.
204 *
205 * Examples:
206 *
207 * req.get('/')
208 * .set('Accept', 'application/json')
209 * .set('X-API-Key', 'foobar')
210 * .end(callback);
211 *
212 * req.get('/')
213 * .set({ Accept: 'application/json', 'X-API-Key': 'foobar' })
214 * .end(callback);
215 *
216 * @param {String|Object} field
217 * @param {String} val
218 * @return {Request} for chaining
219 * @api public
220 */
221
2221Request.prototype.set = function(field, val){
2230 if (isObject(field)) {
2240 for (var key in field) {
2250 this.set(key, field[key]);
226 }
2270 return this;
228 }
229
2300 debug('set %s "%s"', field, val);
2310 this.request().setHeader(field, val);
2320 return this;
233};
234
235/**
236 * Get request header `field`.
237 *
238 * @param {String} field
239 * @return {String}
240 * @api public
241 */
242
2431Request.prototype.get = function(field){
2440 return this.request().getHeader(field);
245};
246
247/**
248 * Set _Content-Type_ response header passed through `mime.lookup()`.
249 *
250 * Examples:
251 *
252 * request.post('/')
253 * .type('xml')
254 * .send(xmlstring)
255 * .end(callback);
256 *
257 * request.post('/')
258 * .type('json')
259 * .send(jsonstring)
260 * .end(callback);
261 *
262 * request.post('/')
263 * .type('application/json')
264 * .send(jsonstring)
265 * .end(callback);
266 *
267 * @param {String} type
268 * @return {Request} for chaining
269 * @api public
270 */
271
2721Request.prototype.type = function(type){
2730 return this.set('Content-Type', ~type.indexOf('/')
274 ? type
275 : mime.lookup(type));
276};
277
278/**
279 * Set _Accept_ response header passed through `mime.lookup()`.
280 *
281 * Examples:
282 *
283 * superagent.types.json = 'application/json';
284 *
285 * request.get('/agent')
286 * .accept('json')
287 * .end(callback);
288 *
289 * request.get('/agent')
290 * .accept('application/json')
291 * .end(callback);
292 *
293 * @param {String} accept
294 * @return {Request} for chaining
295 * @api public
296 */
297
2981Request.prototype.accept = function(type){
2990 return this.set('Accept', ~type.indexOf('/')
300 ? type
301 : mime.lookup(type));
302};
303
304/**
305 * Add query-string `val`.
306 *
307 * Examples:
308 *
309 * request.get('/shoes')
310 * .query('size=10')
311 * .query({ color: 'blue' })
312 *
313 * @param {Object|String} val
314 * @return {Request} for chaining
315 * @api public
316 */
317
3181Request.prototype.query = function(val){
3190 var req = this.request();
3200 if ('string' != typeof val) val = qs.stringify(val);
3210 if (!val.length) return this;
3220 debug('query %s', val);
3230 req.path += (~req.path.indexOf('?') ? '&' : '?') + val;
3240 return this;
325};
326
327/**
328 * Send `data`, defaulting the `.type()` to "json" when
329 * an object is given.
330 *
331 * Examples:
332 *
333 * // manual json
334 * request.post('/user')
335 * .type('json')
336 * .send('{"name":"tj"}')
337 * .end(callback)
338 *
339 * // auto json
340 * request.post('/user')
341 * .send({ name: 'tj' })
342 * .end(callback)
343 *
344 * // manual x-www-form-urlencoded
345 * request.post('/user')
346 * .type('form')
347 * .send('name=tj')
348 * .end(callback)
349 *
350 * // auto x-www-form-urlencoded
351 * request.post('/user')
352 * .type('form')
353 * .send({ name: 'tj' })
354 * .end(callback)
355 *
356 * // string defaults to x-www-form-urlencoded
357 * request.post('/user')
358 * .send('name=tj')
359 * .send('foo=bar')
360 * .send('bar=baz')
361 * .end(callback)
362 *
363 * @param {String|Object} data
364 * @return {Request} for chaining
365 * @api public
366 */
367
3681Request.prototype.send = function(data){
3690 var obj = isObject(data);
3700 var req = this.request();
3710 var type = req.getHeader('Content-Type');
372
373 // merge
3740 if (obj && isObject(this._data)) {
3750 for (var key in data) {
3760 this._data[key] = data[key];
377 }
378 // string
3790 } else if ('string' == typeof data) {
380 // default to x-www-form-urlencoded
3810 if (!type) this.type('form');
3820 type = req.getHeader('Content-Type');
383
384 // concat &
3850 if ('application/x-www-form-urlencoded' == type) {
3860 this._data = this._data
387 ? this._data + '&' + data
388 : data;
389 } else {
3900 this._data = (this._data || '') + data;
391 }
392 } else {
3930 this._data = data;
394 }
395
3960 if (!obj) return this;
397
398 // default to json
3990 if (!type) this.type('json');
4000 return this;
401};
402
403/**
404 * Write raw `data` / `encoding` to the socket.
405 *
406 * @param {Buffer|String} data
407 * @param {String} encoding
408 * @return {Boolean}
409 * @api public
410 */
411
4121Request.prototype.write = function(data, encoding){
4130 return this.request().write(data, encoding);
414};
415
416/**
417 * Pipe the request body to `stream`.
418 *
419 * @param {Stream} stream
420 * @param {Object} options
421 * @return {Stream}
422 * @api public
423 */
424
4251Request.prototype.pipe = function(stream, options){
4260 this.piped = true; // HACK...
4270 this.buffer(false);
4280 this.end().req.on('response', function(res){
4290 if (/^(deflate|gzip)$/.test(res.headers['content-encoding'])) {
4300 res.pipe(zlib.createUnzip()).pipe(stream, options);
431 } else {
4320 res.pipe(stream, options);
433 }
434 });
4350 return stream;
436};
437
438/**
439 * Enable / disable buffering.
440 *
441 * @return {Boolean} [val]
442 * @return {Request} for chaining
443 * @api public
444 */
445
4461Request.prototype.buffer = function(val){
4470 this._buffer = false === val
448 ? false
449 : true;
4500 return this;
451};
452
453/**
454 * Set timeout to `ms`.
455 *
456 * @param {Number} ms
457 * @return {Request} for chaining
458 * @api public
459 */
460
4611Request.prototype.timeout = function(ms){
4620 this._timeout = ms;
4630 return this;
464};
465
466/**
467 * Clear previous timeout.
468 *
469 * @return {Request} for chaining
470 * @api public
471 */
472
4731Request.prototype.clearTimeout = function(){
4740 debug('clear timeout %s %s', this.method, this.url);
4750 this._timeout = 0;
4760 clearTimeout(this._timer);
4770 return this;
478};
479
480/**
481 * Abort and clear timeout.
482 *
483 * @api public
484 */
485
4861Request.prototype.abort = function(){
4870 debug('abort %s %s', this.method, this.url);
4880 this._aborted = true;
4890 this.clearTimeout();
4900 this.req.abort();
491};
492
493/**
494 * Define the parser to be used for this response.
495 *
496 * @param {Function} fn
497 * @return {Request} for chaining
498 * @api public
499 */
500
5011Request.prototype.parse = function(fn){
5020 this._parser = fn;
5030 return this;
504};
505
506/**
507 * Redirect to `url
508 *
509 * @param {IncomingMessage} res
510 * @return {Request} for chaining
511 * @api private
512 */
513
5141Request.prototype.redirect = function(res){
5150 var url = res.headers.location;
5160 debug('redirect %s -> %s', this.url, url);
517
518 // location
5190 if (!~url.indexOf('://')) {
5200 if (0 != url.indexOf('//')) {
5210 url = '//' + this.host + url;
522 }
5230 url = this.protocol + url;
524 }
525
526 // ensure the response is being consumed
527 // this is required for Node v0.10+
5280 res.resume();
529
530 // strip Content-* related fields
531 // in case of POST etc
5320 var header = utils.cleanHeader(this.req._headers);
5330 delete this.req;
534
535 // force GET
5360 this.method = 'HEAD' == this.method
537 ? 'HEAD'
538 : 'GET';
539
540 // redirect
5410 this._data = null;
5420 this.url = url;
5430 this._redirectList.push(url);
5440 this.clearTimeout();
5450 this.emit('redirect', res);
5460 this.set(header);
5470 this.end(this._callback);
5480 return this;
549};
550
551/**
552 * Set Authorization field value with `user` and `pass`.
553 *
554 * @param {String} user
555 * @param {String} pass
556 * @return {Request} for chaining
557 * @api public
558 */
559
5601Request.prototype.auth = function(user, pass){
5610 var str = new Buffer(user + ':' + pass).toString('base64');
5620 return this.set('Authorization', 'Basic ' + str);
563};
564
565/**
566 * Write the field `name` and `val`.
567 *
568 * @param {String} name
569 * @param {String} val
570 * @return {Request} for chaining
571 * @api public
572 */
573
5741Request.prototype.field = function(name, val){
5750 this.part().name(name).write(String(val));
5760 return this;
577};
578
579/**
580 * Return an http[s] request.
581 *
582 * @return {OutgoingMessage}
583 * @api private
584 */
585
5861Request.prototype.request = function(){
5870 if (this.req) return this.req;
588
5890 var self = this;
5900 var options = {};
5910 var data = this._data;
5920 var url = this.url;
593
594 // default to http://
5950 if (0 != url.indexOf('http')) url = 'http://' + url;
5960 url = parse(url, true);
597
598 // options
5990 options.method = this.method;
6000 options.port = url.port;
6010 options.path = url.pathname;
6020 options.host = url.hostname;
6030 options.agent = this._agent;
604
605 // initiate request
6060 var mod = exports.protocols[url.protocol];
607
608 // request
6090 var req = this.req = mod.request(options);
6100 if ('HEAD' != options.method) req.setHeader('Accept-Encoding', 'gzip, deflate');
6110 this.protocol = url.protocol;
6120 this.host = url.host;
613
614 // expose events
6150 req.on('drain', function(){ self.emit('drain'); });
616
6170 req.on('error', function(err){
618 // flag abortion here for out timeouts
619 // because node will emit a faux-error "socket hang up"
620 // when request is aborted before a connection is made
6210 if (self._aborted) return;
6220 self.callback(err);
623 });
624
625 // auth
6260 if (url.auth) {
6270 var auth = url.auth.split(':');
6280 this.auth(auth[0], auth[1]);
629 }
630
631 // query
6320 this.query(url.query);
633
634 // add cookies
6350 req.setHeader('Cookie', this.cookies);
636
6370 return req;
638};
639
640/**
641 * Invoke the callback with `err` and `res`
642 * and handle arity check.
643 *
644 * @param {Error} err
645 * @param {Response} res
646 * @api private
647 */
648
6491Request.prototype.callback = function(err, res){
6500 var fn = this._callback;
6510 this.clearTimeout();
6520 if (this.called) return console.warn('double callback!');
6530 this.called = true;
6540 if (2 == fn.length) return fn(err, res);
6550 if (err) return this.emit('error', err);
6560 fn(res);
657};
658
659/**
660 * Initiate request, invoking callback `fn(err, res)`
661 * with an instanceof `Response`.
662 *
663 * @param {Function} fn
664 * @return {Request} for chaining
665 * @api public
666 */
667
6681Request.prototype.end = function(fn){
6690 var self = this;
6700 var data = this._data;
6710 var req = this.request();
6720 var buffer = this._buffer;
6730 var method = this.method;
6740 var timeout = this._timeout;
6750 debug('%s %s', this.method, this.url);
676
677 // store callback
6780 this._callback = fn || noop;
679
680 // timeout
6810 if (timeout && !this._timer) {
6820 debug('timeout %sms %s %s', timeout, this.method, this.url);
6830 this._timer = setTimeout(function(){
6840 var err = new Error('timeout of ' + timeout + 'ms exceeded');
6850 err.timeout = timeout;
6860 self.abort();
6870 self.callback(err);
688 }, timeout);
689 }
690
691 // body
6920 if ('HEAD' != method && !req._headerSent) {
693 // serialize stuff
6940 if ('string' != typeof data) {
6950 var contentType = req.getHeader('Content-Type')
696 // Parse out just the content type from the header (ignore the charset)
6970 if (contentType) contentType = contentType.split(';')[0]
6980 var serialize = exports.serialize[contentType];
6990 if (serialize) data = serialize(data);
700 }
701
702 // content-length
7030 if (data && !req.getHeader('Content-Length')) {
7040 this.set('Content-Length', Buffer.byteLength(data));
705 }
706 }
707
708 // response
7090 req.on('response', function(res){
7100 debug('%s %s -> %s', self.method, self.url, res.statusCode);
7110 var max = self._maxRedirects;
7120 var mime = utils.type(res.headers['content-type'] || '');
7130 var len = res.headers['content-length'];
7140 var type = mime.split('/');
7150 var subtype = type[1];
7160 var type = type[0];
7170 var multipart = 'multipart' == type;
7180 var redirect = isRedirect(res.statusCode);
719
7200 if (self.piped) {
7210 res.on('end', function(){
7220 self.emit('end');
723 });
7240 return;
725 }
726
727 // redirect
7280 if (redirect && self._redirects++ != max) {
7290 return self.redirect(res);
730 }
731
732 // zlib support
7330 if (/^(deflate|gzip)$/.test(res.headers['content-encoding'])) {
7340 utils.unzip(req, res);
735 }
736
737 // don't buffer multipart
7380 if (multipart) buffer = false;
739
740 // TODO: make all parsers take callbacks
7410 if (multipart) {
7420 var form = new formidable.IncomingForm;
743
7440 form.parse(res, function(err, fields, files){
7450 if (err) return self.callback(err);
7460 var response = new Response(req, res);
7470 response.body = fields;
7480 response.files = files;
7490 response.redirects = self._redirectList;
7500 self.emit('end');
7510 self.callback(null, response);
752 });
7530 return;
754 }
755
756 // by default only buffer text/*, json
757 // and messed up thing from hell
7580 var text = isText(mime);
7590 if (null == buffer && text) buffer = true;
760
761 // parser
7620 var parse = 'text' == type
763 ? exports.parse.text
764 : exports.parse[mime];
765
766 // buffered response
7670 if (buffer) parse = parse || exports.parse.text;
768
769 // explicit parser
7700 if (self._parser) parse = self._parser;
771
772 // parse
7730 if (parse) {
7740 parse(res, function(err, obj){
775 // TODO: handle error
7760 res.body = obj;
777 });
778 }
779
780 // unbuffered
7810 if (!buffer) {
7820 debug('unbuffered %s %s', self.method, self.url);
7830 self.res = res;
7840 var response = new Response(self.req, self.res);
7850 response.redirects = self._redirectList;
7860 self.emit('response', response);
7870 if (multipart) return // allow multipart to handle end event
7880 res.on('end', function(){
7890 debug('end %s %s', self.method, self.url);
7900 self.emit('end');
791 })
7920 return;
793 }
794
795 // end event
7960 self.res = res;
7970 res.on('end', function(){
7980 debug('end %s %s', self.method, self.url);
799 // TODO: unless buffering emit earlier to stream
8000 var response = new Response(self.req, self.res);
8010 response.redirects = self._redirectList;
8020 self.emit('response', response);
8030 self.emit('end');
804 });
805 });
806
8070 if (this.attachments.length) return this.writeAttachments();
808
809 // multi-part boundary
8100 if (this._boundary) this.writeFinalBoundary();
811
8120 req.end(data);
8130 return this;
814};
815
816/**
817 * Write the final boundary.
818 *
819 * @api private
820 */
821
8221Request.prototype.writeFinalBoundary = function(){
8230 this.request().write('\r\n--' + this._boundary + '--');
824};
825
826/**
827 * Get total bytesize of all attachments.
828 *
829 * @param {Function} fn
830 * @api private
831 */
832
8331Request.prototype.attachmentSize = function(fn){
8340 var files = this.attachments;
8350 var pending = files.length;
8360 var bytes = 0;
8370 var self = this;
838
8390 files.forEach(function(file){
8400 fs.stat(file.path, function(err, s){
8410 if (s) bytes += s.size;
8420 --pending || fn(bytes);
843 });
844 })
845};
846
847/**
848 * Write the attachments in sequence.
849 *
850 * @api private
851 */
852
8531Request.prototype.writeAttachments = function(){
8540 var files = this.attachments;
8550 var req = this.request();
8560 var written = 0;
8570 var self = this;
858
8590 this.attachmentSize(function(total){
8600 function next() {
8610 var file = files.shift();
8620 if (!file) {
8630 self.writeFinalBoundary();
8640 return req.end();
865 }
866
8670 file.part.attachment(file.field, file.filename);
8680 var stream = fs.createReadStream(file.path);
869
870 // TODO: pipe
871 // TODO: handle errors
8720 stream.on('data', function(data){
8730 written += data.length;
8740 file.part.write(data);
8750 self.emit('progress', {
876 percent: written / total * 100 | 0,
877 written: written,
878 total: total
879 });
880 }).on('error', function(err){
8810 self.emit('error', err);
882 }).on('end', next);
883 }
884
8850 next();
886 })
887};
888
889/**
890 * Expose `Request`.
891 */
892
8931exports.Request = Request;
894
895/**
896 * Issue a request:
897 *
898 * Examples:
899 *
900 * request('GET', '/users').end(callback)
901 * request('/users').end(callback)
902 * request('/users', callback)
903 *
904 * @param {String} method
905 * @param {String|Function} url or callback
906 * @return {Request}
907 * @api public
908 */
909
9101function request(method, url) {
911 // callback
9120 if ('function' == typeof url) {
9130 return new Request('GET', method).end(url);
914 }
915
916 // url first
9170 if (1 == arguments.length) {
9180 return new Request('GET', method);
919 }
920
9210 return new Request(method, url);
922}
923
924// generate HTTP verb methods
925
9261methods.forEach(function(method){
92723 var name = 'delete' == method ? 'del' : method;
92823 method = method.toUpperCase();
92923 request[name] = function(url, fn){
9300 var req = request(method, url);
9310 fn && req.end(fn);
9320 return req;
933 };
934});
935
936/**
937 * Check if `mime` is text and should be buffered.
938 *
939 * @param {String} mime
940 * @return {Boolean}
941 * @api public
942 */
943
9441function isText(mime) {
9450 var parts = mime.split('/');
9460 var type = parts[0];
9470 var subtype = parts[1];
948
9490 return 'text' == type
950 || 'json' == subtype
951 || 'x-www-form-urlencoded' == subtype;
952}
953
954/**
955 * Check if we should follow the redirect `code`.
956 *
957 * @param {Number} code
958 * @return {Boolean}
959 * @api private
960 */
961
9621function isRedirect(code) {
9630 return ~[301, 302, 303, 305, 307].indexOf(code);
964}
965

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/lib/node/parsers/index.js

100%
3
3
0
LineHitsSource
1
21exports['application/x-www-form-urlencoded'] = require('./urlencoded');
31exports['application/json'] = require('./json');
41exports.text = require('./text');
5

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/lib/node/parsers/json.js

12%
8
1
7
LineHitsSource
1
21module.exports = function(res, fn){
30 res.text = '';
40 res.setEncoding('utf8');
50 res.on('data', function(chunk){ res.text += chunk; });
60 res.on('end', function(){
70 try {
80 fn(null, JSON.parse(res.text));
9 } catch (err) {
100 fn(err);
11 }
12 });
13};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/lib/node/parsers/text.js

20%
5
1
4
LineHitsSource
1
21module.exports = function(res, fn){
30 res.text = '';
40 res.setEncoding('utf8');
50 res.on('data', function(chunk){ res.text += chunk; });
60 res.on('end', fn);
7};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/lib/node/parsers/urlencoded.js

22%
9
2
7
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var qs = require('qs');
7
81module.exports = function(res, fn){
90 res.text = '';
100 res.setEncoding('ascii');
110 res.on('data', function(chunk){ res.text += chunk; });
120 res.on('end', function(){
130 try {
140 fn(null, qs.parse(res.text));
15 } catch (err) {
160 fn(err);
17 }
18 });
19};

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/lib/node/part.js

34%
44
15
29
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var utils = require('./utils');
71var Stream = require('stream').Stream;
81var mime = require('mime');
91var path = require('path');
101var basename = path.basename;
11
12/**
13 * Expose `Part`.
14 */
15
161module.exports = Part;
17
18/**
19 * Initialize a new `Part` for the given `req`.
20 *
21 * @param {Request} req
22 * @api public
23 */
24
251function Part(req) {
260 this.req = req;
270 this.header = {};
280 this.headerSent = false;
290 this.request = req.request();
300 this.writable = true;
310 if (!req._boundary) this.assignBoundary();
32}
33
34/**
35 * Inherit from `Stream.prototype`.
36 */
37
381Part.prototype.__proto__ = Stream.prototype;
39
40/**
41 * Assign the initial request-level boundary.
42 *
43 * @api private
44 */
45
461Part.prototype.assignBoundary = function(){
470 var boundary = utils.uid(32);
480 this.req.set('Content-Type', 'multipart/form-data; boundary=' + boundary);
490 this.req._boundary = boundary;
50};
51
52/**
53 * Set header `field` to `val`.
54 *
55 * @param {String} field
56 * @param {String} val
57 * @return {Part} for chaining
58 * @api public
59 */
60
611Part.prototype.set = function(field, val){
620 if (!this._boundary) {
63 // TODO: formidable bug
640 if (!this.request._hasFirstBoundary) {
650 this.request.write('--' + this.req._boundary + '\r\n');
660 this.request._hasFirstBoundary = true;
67 } else {
680 this.request.write('\r\n--' + this.req._boundary + '\r\n');
69 }
700 this._boundary = true;
71 }
720 this.request.write(field + ': ' + val + '\r\n');
730 return this;
74};
75
76/**
77 * Set _Content-Type_ response header passed through `mime.lookup()`.
78 *
79 * Examples:
80 *
81 * res.type('html');
82 * res.type('.html');
83 *
84 * @param {String} type
85 * @return {Part}
86 * @api public
87 */
88
891Part.prototype.type = function(type){
900 return this.set('Content-Type', mime.lookup(type));
91};
92
93/**
94 * Set _Content-Disposition_ header field to _form-data_
95 * and set the _name_ param to the given string.
96 *
97 * @param {String} name
98 * @return {Part}
99 * @api public
100 */
101
1021Part.prototype.name = function(name){
1030 this.set('Content-Disposition', 'form-data; name="' + name + '"');
1040 return this;
105};
106
107/**
108 * Set _Content-Disposition_ header field to _attachment_ with `filename`
109 * and field `name`.
110 *
111 * @param {String} name
112 * @param {String} filename
113 * @return {Part}
114 * @api public
115 */
116
1171Part.prototype.attachment = function(name, filename){
1180 this.type(filename);
1190 this.set('Content-Disposition', 'attachment; name="' + name + '"; filename="' + basename(filename) + '"');
1200 return this;
121};
122
123/**
124 * Write `data` with `encoding`.
125 *
126 * @param {Buffer|String} data
127 * @param {String} encoding
128 * @return {Boolean}
129 * @api public
130 */
131
1321Part.prototype.write = function(data, encoding){
1330 if (!this._headerCRLF) {
1340 this.request.write('\r\n');
1350 this._headerCRLF = true;
136 }
1370 return this.request.write(data, encoding);
138};
139
140/**
141 * End the part.
142 *
143 * @api public
144 */
145
1461Part.prototype.end = function(){
1470 this.emit('end');
1480 this.complete = true;
149};
150
151

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/lib/node/response.js

20%
65
13
52
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var utils = require('./utils');
71var Stream = require('stream');
8
9/**
10 * Expose `Response`.
11 */
12
131module.exports = Response;
14
15/**
16 * Initialize a new `Response` with the given `xhr`.
17 *
18 * - set flags (.ok, .error, etc)
19 * - parse header
20 *
21 * @param {ClientRequest} req
22 * @param {IncomingMessage} res
23 * @param {Object} options
24 * @constructor
25 * @extends {Stream}
26 * @implements {ReadableStream}
27 * @api private
28 */
29
301function Response(req, res, options) {
310 options = options || {};
320 this.req = req;
330 this.res = res;
340 this.links = {};
350 this.text = res.text;
360 this.body = res.body || {};
370 this.files = res.files || {};
380 this.buffered = 'string' == typeof this.text;
390 this.header = this.headers = res.headers;
400 this.setStatusProperties(res.statusCode);
410 this.setHeaderProperties(this.header);
420 this.setEncoding = res.setEncoding.bind(res);
430 res.on('data', this.emit.bind(this, 'data'));
440 res.on('end', this.emit.bind(this, 'end'));
450 res.on('close', this.emit.bind(this, 'close'));
460 res.on('error', this.emit.bind(this, 'error'));
47}
48
49/**
50 * Inherits from `Stream.prototype`.
51 */
52
531Response.prototype.__proto__ = Stream.prototype;
54
55/**
56 * Get case-insensitive `field` value.
57 *
58 * @param {String} field
59 * @return {String}
60 * @api public
61 */
62
631Response.prototype.get = function(field){
640 return this.header[field.toLowerCase()];
65};
66
67/**
68 * Implements methods of a `ReadableStream`
69 */
70
711Response.prototype.destroy = function(err){
720 this.res.destroy(err);
73};
74
75/**
76 * Pause.
77 */
78
791Response.prototype.pause = function(){
800 this.res.pause();
81};
82
83/**
84 * Resume.
85 */
86
871Response.prototype.resume = function(){
880 this.res.resume();
89};
90
91/**
92 * Return an `Error` representative of this response.
93 *
94 * @return {Error}
95 * @api public
96 */
97
981Response.prototype.toError = function(){
990 var req = this.req;
1000 var method = req.method;
1010 var path = req.path;
102
1030 var msg = 'cannot ' + method + ' ' + path + ' (' + this.status + ')';
1040 var err = new Error(msg);
1050 err.status = this.status;
1060 err.method = method;
1070 err.path = path;
108
1090 return err;
110};
111
112/**
113 * Set header related properties:
114 *
115 * - `.type` the content type without params
116 *
117 * A response of "Content-Type: text/plain; charset=utf-8"
118 * will provide you with a `.type` of "text/plain".
119 *
120 * @param {Object} header
121 * @api private
122 */
123
1241Response.prototype.setHeaderProperties = function(header){
125 // TODO: moar!
126 // TODO: make this a util
127
128 // content-type
1290 var ct = this.header['content-type'] || '';
130
131 // params
1320 var params = utils.params(ct);
1330 for (var key in params) this[key] = params[key];
134
1350 this.type = utils.type(ct);
136
137 // links
1380 try {
1390 if (header.link) this.links = utils.parseLinks(header.link);
140 } catch (err) {
141 // ignore
142 }
143};
144
145/**
146 * Parse cookies from the header into an array.
147 */
148
1491function parseCookies(header) {
1500 return Array.isArray(header)
151 ? header.map(Cookie.parse)
152 : [Cookie.parse(header)];
153}
154
155/**
156 * Set flags such as `.ok` based on `status`.
157 *
158 * For example a 2xx response will give you a `.ok` of __true__
159 * whereas 5xx will be __false__ and `.error` will be __true__. The
160 * `.clientError` and `.serverError` are also available to be more
161 * specific, and `.statusType` is the class of error ranging from 1..5
162 * sometimes useful for mapping respond colors etc.
163 *
164 * "sugar" properties are also defined for common cases. Currently providing:
165 *
166 * - .noContent
167 * - .badRequest
168 * - .unauthorized
169 * - .notAcceptable
170 * - .notFound
171 *
172 * @param {Number} status
173 * @api private
174 */
175
1761Response.prototype.setStatusProperties = function(status){
1770 var type = status / 100 | 0;
178
179 // status / class
1800 this.status = this.statusCode = status;
1810 this.statusType = type;
182
183 // basics
1840 this.info = 1 == type;
1850 this.ok = 2 == type;
1860 this.redirect = 3 == type;
1870 this.clientError = 4 == type;
1880 this.serverError = 5 == type;
1890 this.error = (4 == type || 5 == type)
190 ? this.toError()
191 : false;
192
193 // sugar
1940 this.accepted = 202 == status;
1950 this.noContent = 204 == status;
1960 this.badRequest = 400 == status;
1970 this.unauthorized = 401 == status;
1980 this.notAcceptable = 406 == status;
1990 this.forbidden = 403 == status;
2000 this.notFound = 404 == status;
201};
202

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/lib/node/utils.js

18%
60
11
49
LineHitsSource
1
2/**
3 * Module dependencies.
4 */
5
61var StringDecoder = require('string_decoder').StringDecoder;
71var Stream = require('stream');
81var zlib;
9
10/**
11 * Require zlib module for Node 0.6+
12 */
13
141try {
151 zlib = require('zlib');
16} catch (e) { }
17
18/**
19 * Generate a UID with the given `len`.
20 *
21 * @param {Number} len
22 * @return {String}
23 * @api private
24 */
25
261exports.uid = function(len){
270 var buf = '';
280 var chars = 'abcdefghijklmnopqrstuvwxyz123456789';
290 var nchars = chars.length;
300 while (len--) buf += chars[Math.random() * nchars | 0];
310 return buf;
32};
33
34/**
35 * Return the mime type for the given `str`.
36 *
37 * @param {String} str
38 * @return {String}
39 * @api private
40 */
41
421exports.type = function(str){
430 return str.split(/ *; */).shift();
44};
45
46/**
47 * Return header field parameters.
48 *
49 * @param {String} str
50 * @return {Object}
51 * @api private
52 */
53
541exports.params = function(str){
550 return str.split(/ *; */).reduce(function(obj, str){
560 var parts = str.split(/ *= */);
570 var key = parts.shift();
580 var val = parts.shift();
59
600 if (key && val) obj[key] = val;
610 return obj;
62 }, {});
63};
64
65/**
66 * Parse Link header fields.
67 *
68 * @param {String} str
69 * @return {Object}
70 * @api private
71 */
72
731exports.parseLinks = function(str){
740 return str.split(/ *, */).reduce(function(obj, str){
750 var parts = str.split(/ *; */);
760 var url = parts[0].slice(1, -1);
770 var rel = parts[1].split(/ *= */)[1].slice(1, -1);
780 obj[rel] = url;
790 return obj;
80 }, {});
81};
82
83/**
84 * Buffers response data events and re-emits when they're unzipped.
85 *
86 * @param {Request} req
87 * @param {Response} res
88 * @api private
89 */
90
911exports.unzip = function(req, res){
920 if (!zlib) return;
93
940 var unzip = zlib.createUnzip();
950 var stream = new Stream;
960 var decoder;
97
98 // make node responseOnEnd() happy
990 stream.req = req;
100
1010 unzip.on('error', function(err){
1020 stream.emit('error', err);
103 });
104
105 // pipe to unzip
1060 res.pipe(unzip);
107
108 // override `setEncoding` to capture encoding
1090 res.setEncoding = function(type){
1100 decoder = new StringDecoder(type);
111 };
112
113 // decode upon decompressing with captured encoding
1140 unzip.on('data', function(buf){
1150 if (decoder) {
1160 var str = decoder.write(buf);
1170 if (str.length) stream.emit('data', str);
118 } else {
1190 stream.emit('data', buf);
120 }
121 });
122
1230 unzip.on('end', function(){
1240 stream.emit('end');
125 });
126
127 // override `on` to capture data listeners
1280 var _on = res.on;
1290 res.on = function(type, fn){
1300 if ('data' == type || 'end' == type) {
1310 stream.on(type, fn);
1320 } else if ('error' == type) {
1330 stream.on(type, fn);
1340 _on.call(res, type, fn);
135 } else {
1360 _on.call(res, type, fn);
137 }
138 };
139};
140
141/**
142 * Strip content related fields from `header`.
143 *
144 * @param {Object} header
145 * @return {Object} header
146 * @api private
147 */
148
1491exports.cleanHeader = function(header){
1500 delete header['content-type'];
1510 delete header['content-length'];
1520 delete header['transfer-encoding'];
1530 delete header['cookie'];
1540 delete header['host'];
1550 return header;
156};
157

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/node_modules/debug/lib/debug.js

47%
46
22
24
LineHitsSource
1/**
2 * Module dependencies.
3 */
4
51var tty = require('tty');
6
7/**
8 * Expose `debug()` as the module.
9 */
10
111module.exports = debug;
12
13/**
14 * Enabled debuggers.
15 */
16
171var names = []
18 , skips = [];
19
201(process.env.DEBUG || '')
21 .split(/[\s,]+/)
22 .forEach(function(name){
231 name = name.replace('*', '.*?');
241 if (name[0] === '-') {
250 skips.push(new RegExp('^' + name.substr(1) + '$'));
26 } else {
271 names.push(new RegExp('^' + name + '$'));
28 }
29 });
30
31/**
32 * Colors.
33 */
34
351var colors = [6, 2, 3, 4, 5, 1];
36
37/**
38 * Previous debug() call.
39 */
40
411var prev = {};
42
43/**
44 * Previously assigned color.
45 */
46
471var prevColor = 0;
48
49/**
50 * Is stdout a TTY? Colored output is disabled when `true`.
51 */
52
531var isatty = tty.isatty(2);
54
55/**
56 * Select a color.
57 *
58 * @return {Number}
59 * @api private
60 */
61
621function color() {
630 return colors[prevColor++ % colors.length];
64}
65
66/**
67 * Humanize the given `ms`.
68 *
69 * @param {Number} m
70 * @return {String}
71 * @api private
72 */
73
741function humanize(ms) {
750 var sec = 1000
76 , min = 60 * 1000
77 , hour = 60 * min;
78
790 if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
800 if (ms >= min) return (ms / min).toFixed(1) + 'm';
810 if (ms >= sec) return (ms / sec | 0) + 's';
820 return ms + 'ms';
83}
84
85/**
86 * Create a debugger with the given `name`.
87 *
88 * @param {String} name
89 * @return {Type}
90 * @api public
91 */
92
931function debug(name) {
941 function disabled(){}
951 disabled.enabled = false;
96
971 var match = skips.some(function(re){
980 return re.test(name);
99 });
100
1011 if (match) return disabled;
102
1031 match = names.some(function(re){
1041 return re.test(name);
105 });
106
1072 if (!match) return disabled;
1080 var c = color();
109
1100 function colored(fmt) {
1110 fmt = coerce(fmt);
112
1130 var curr = new Date;
1140 var ms = curr - (prev[name] || curr);
1150 prev[name] = curr;
116
1170 fmt = ' \u001b[9' + c + 'm' + name + ' '
118 + '\u001b[3' + c + 'm\u001b[90m'
119 + fmt + '\u001b[3' + c + 'm'
120 + ' +' + humanize(ms) + '\u001b[0m';
121
1220 console.error.apply(this, arguments);
123 }
124
1250 function plain(fmt) {
1260 fmt = coerce(fmt);
127
1280 fmt = new Date().toUTCString()
129 + ' ' + name + ' ' + fmt;
1300 console.error.apply(this, arguments);
131 }
132
1330 colored.enabled = plain.enabled = true;
134
1350 return isatty || process.env.DEBUG_COLORS
136 ? colored
137 : plain;
138}
139
140/**
141 * Coerce `val`.
142 */
143
1441function coerce(val) {
1450 if (val instanceof Error) return val.stack || val.message;
1460 return val;
147}
148

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/file.js

23%
38
9
29
LineHitsSource
11if (global.GENTLY) require = GENTLY.hijack(require);
2
31var util = require('util'),
4 WriteStream = require('fs').WriteStream,
5 EventEmitter = require('events').EventEmitter,
6 crypto = require('crypto');
7
81function File(properties) {
90 EventEmitter.call(this);
10
110 this.size = 0;
120 this.path = null;
130 this.name = null;
140 this.type = null;
150 this.hash = null;
160 this.lastModifiedDate = null;
17
180 this._writeStream = null;
19
200 for (var key in properties) {
210 this[key] = properties[key];
22 }
23
240 if(typeof this.hash === 'string') {
250 this.hash = crypto.createHash(properties.hash);
26 } else {
270 this.hash = null;
28 }
29}
301module.exports = File;
311util.inherits(File, EventEmitter);
32
331File.prototype.open = function() {
340 this._writeStream = new WriteStream(this.path);
35};
36
371File.prototype.toJSON = function() {
380 return {
39 size: this.size,
40 path: this.path,
41 name: this.name,
42 type: this.type,
43 mtime: this.lastModifiedDate,
44 length: this.length,
45 filename: this.filename,
46 mime: this.mime
47 };
48};
49
501File.prototype.write = function(buffer, cb) {
510 var self = this;
520 if (self.hash) {
530 self.hash.update(buffer);
54 }
550 this._writeStream.write(buffer, function() {
560 self.lastModifiedDate = new Date();
570 self.size += buffer.length;
580 self.emit('progress', self.size);
590 cb();
60 });
61};
62
631File.prototype.end = function(cb) {
640 var self = this;
650 if (self.hash) {
660 self.hash = self.hash.digest('hex');
67 }
680 this._writeStream.end(function() {
690 self.emit('end');
700 cb();
71 });
72};
73

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/incoming_form.js

8%
280
25
255
LineHitsSource
11if (global.GENTLY) require = GENTLY.hijack(require);
2
31var fs = require('fs');
41var util = require('util'),
5 path = require('path'),
6 File = require('./file'),
7 MultipartParser = require('./multipart_parser').MultipartParser,
8 QuerystringParser = require('./querystring_parser').QuerystringParser,
9 OctetParser = require('./octet_parser').OctetParser,
10 JSONParser = require('./json_parser').JSONParser,
11 StringDecoder = require('string_decoder').StringDecoder,
12 EventEmitter = require('events').EventEmitter,
13 Stream = require('stream').Stream,
14 os = require('os');
15
161function IncomingForm(opts) {
170 if (!(this instanceof IncomingForm)) return new IncomingForm(opts);
180 EventEmitter.call(this);
19
200 opts=opts||{};
21
220 this.error = null;
230 this.ended = false;
24
250 this.maxFields = opts.maxFields || 1000;
260 this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024;
270 this.keepExtensions = opts.keepExtensions || false;
280 this.uploadDir = opts.uploadDir || os.tmpDir();
290 this.encoding = opts.encoding || 'utf-8';
300 this.headers = null;
310 this.type = null;
320 this.hash = false;
33
340 this.bytesReceived = null;
350 this.bytesExpected = null;
36
370 this._parser = null;
380 this._flushing = 0;
390 this._fieldsSize = 0;
400 this.openedFiles = [];
41
420 return this;
43};
441util.inherits(IncomingForm, EventEmitter);
451exports.IncomingForm = IncomingForm;
46
471IncomingForm.prototype.parse = function(req, cb) {
480 this.pause = function() {
490 try {
500 req.pause();
51 } catch (err) {
52 // the stream was destroyed
530 if (!this.ended) {
54 // before it was completed, crash & burn
550 this._error(err);
56 }
570 return false;
58 }
590 return true;
60 };
61
620 this.resume = function() {
630 try {
640 req.resume();
65 } catch (err) {
66 // the stream was destroyed
670 if (!this.ended) {
68 // before it was completed, crash & burn
690 this._error(err);
70 }
710 return false;
72 }
73
740 return true;
75 };
76
77 // Setup callback first, so we don't miss anything from data events emitted
78 // immediately.
790 if (cb) {
800 var fields = {}, files = {};
810 this
82 .on('field', function(name, value) {
830 fields[name] = value;
84 })
85 .on('file', function(name, file) {
860 files[name] = file;
87 })
88 .on('error', function(err) {
890 cb(err, fields, files);
90 })
91 .on('end', function() {
920 cb(null, fields, files);
93 });
94 }
95
96 // Parse headers and setup the parser, ready to start listening for data.
970 this.writeHeaders(req.headers);
98
99 // Start listening for data.
1000 var self = this;
1010 req
102 .on('error', function(err) {
1030 self._error(err);
104 })
105 .on('aborted', function() {
1060 self.emit('aborted');
1070 self._error(new Error('Request aborted'));
108 })
109 .on('data', function(buffer) {
1100 self.write(buffer);
111 })
112 .on('end', function() {
1130 if (self.error) {
1140 return;
115 }
116
1170 var err = self._parser.end();
1180 if (err) {
1190 self._error(err);
120 }
121 });
122
1230 return this;
124};
125
1261IncomingForm.prototype.writeHeaders = function(headers) {
1270 this.headers = headers;
1280 this._parseContentLength();
1290 this._parseContentType();
130};
131
1321IncomingForm.prototype.write = function(buffer) {
1330 if (!this._parser) {
1340 this._error(new Error('unintialized parser'));
1350 return;
136 }
137
1380 this.bytesReceived += buffer.length;
1390 this.emit('progress', this.bytesReceived, this.bytesExpected);
140
1410 var bytesParsed = this._parser.write(buffer);
1420 if (bytesParsed !== buffer.length) {
1430 this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed'));
144 }
145
1460 return bytesParsed;
147};
148
1491IncomingForm.prototype.pause = function() {
150 // this does nothing, unless overwritten in IncomingForm.parse
1510 return false;
152};
153
1541IncomingForm.prototype.resume = function() {
155 // this does nothing, unless overwritten in IncomingForm.parse
1560 return false;
157};
158
1591IncomingForm.prototype.onPart = function(part) {
160 // this method can be overwritten by the user
1610 this.handlePart(part);
162};
163
1641IncomingForm.prototype.handlePart = function(part) {
1650 var self = this;
166
1670 if (part.filename === undefined) {
1680 var value = ''
169 , decoder = new StringDecoder(this.encoding);
170
1710 part.on('data', function(buffer) {
1720 self._fieldsSize += buffer.length;
1730 if (self._fieldsSize > self.maxFieldsSize) {
1740 self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data'));
1750 return;
176 }
1770 value += decoder.write(buffer);
178 });
179
1800 part.on('end', function() {
1810 self.emit('field', part.name, value);
182 });
1830 return;
184 }
185
1860 this._flushing++;
187
1880 var file = new File({
189 path: this._uploadPath(part.filename),
190 name: part.filename,
191 type: part.mime,
192 hash: self.hash
193 });
194
1950 this.emit('fileBegin', part.name, file);
196
1970 file.open();
1980 this.openedFiles.push(file);
199
2000 part.on('data', function(buffer) {
2010 self.pause();
2020 file.write(buffer, function() {
2030 self.resume();
204 });
205 });
206
2070 part.on('end', function() {
2080 file.end(function() {
2090 self._flushing--;
2100 self.emit('file', part.name, file);
2110 self._maybeEnd();
212 });
213 });
214};
215
2161function dummyParser(self) {
2170 return {
218 end: function () {
2190 self.ended = true;
2200 self._maybeEnd();
2210 return null;
222 }
223 };
224}
225
2261IncomingForm.prototype._parseContentType = function() {
2270 if (this.bytesExpected === 0) {
2280 this._parser = dummyParser(this);
2290 return;
230 }
231
2320 if (!this.headers['content-type']) {
2330 this._error(new Error('bad content-type header, no content-type'));
2340 return;
235 }
236
2370 if (this.headers['content-type'].match(/octet-stream/i)) {
2380 this._initOctetStream();
2390 return;
240 }
241
2420 if (this.headers['content-type'].match(/urlencoded/i)) {
2430 this._initUrlencoded();
2440 return;
245 }
246
2470 if (this.headers['content-type'].match(/multipart/i)) {
2480 var m;
2490 if (m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i)) {
2500 this._initMultipart(m[1] || m[2]);
251 } else {
2520 this._error(new Error('bad content-type header, no multipart boundary'));
253 }
2540 return;
255 }
256
2570 if (this.headers['content-type'].match(/json/i)) {
2580 this._initJSONencoded();
2590 return;
260 }
261
2620 this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type']));
263};
264
2651IncomingForm.prototype._error = function(err) {
2660 if (this.error || this.ended) {
2670 return;
268 }
269
2700 this.error = err;
2710 this.pause();
2720 this.emit('error', err);
273
2740 if (Array.isArray(this.openedFiles)) {
2750 this.openedFiles.forEach(function(file) {
2760 file._writeStream.destroy();
2770 setTimeout(fs.unlink, 0, file.path);
278 });
279 }
280};
281
2821IncomingForm.prototype._parseContentLength = function() {
2830 this.bytesReceived = 0;
2840 if (this.headers['content-length']) {
2850 this.bytesExpected = parseInt(this.headers['content-length'], 10);
2860 } else if (this.headers['transfer-encoding'] === undefined) {
2870 this.bytesExpected = 0;
288 }
289
2900 if (this.bytesExpected !== null) {
2910 this.emit('progress', this.bytesReceived, this.bytesExpected);
292 }
293};
294
2951IncomingForm.prototype._newParser = function() {
2960 return new MultipartParser();
297};
298
2991IncomingForm.prototype._initMultipart = function(boundary) {
3000 this.type = 'multipart';
301
3020 var parser = new MultipartParser(),
303 self = this,
304 headerField,
305 headerValue,
306 part;
307
3080 parser.initWithBoundary(boundary);
309
3100 parser.onPartBegin = function() {
3110 part = new Stream();
3120 part.readable = true;
3130 part.headers = {};
3140 part.name = null;
3150 part.filename = null;
3160 part.mime = null;
317
3180 part.transferEncoding = 'binary';
3190 part.transferBuffer = '';
320
3210 headerField = '';
3220 headerValue = '';
323 };
324
3250 parser.onHeaderField = function(b, start, end) {
3260 headerField += b.toString(self.encoding, start, end);
327 };
328
3290 parser.onHeaderValue = function(b, start, end) {
3300 headerValue += b.toString(self.encoding, start, end);
331 };
332
3330 parser.onHeaderEnd = function() {
3340 headerField = headerField.toLowerCase();
3350 part.headers[headerField] = headerValue;
336
3370 var m;
3380 if (headerField == 'content-disposition') {
3390 if (m = headerValue.match(/\bname="([^"]+)"/i)) {
3400 part.name = m[1];
341 }
342
3430 part.filename = self._fileName(headerValue);
3440 } else if (headerField == 'content-type') {
3450 part.mime = headerValue;
3460 } else if (headerField == 'content-transfer-encoding') {
3470 part.transferEncoding = headerValue.toLowerCase();
348 }
349
3500 headerField = '';
3510 headerValue = '';
352 };
353
3540 parser.onHeadersEnd = function() {
3550 switch(part.transferEncoding){
356 case 'binary':
357 case '7bit':
358 case '8bit':
3590 parser.onPartData = function(b, start, end) {
3600 part.emit('data', b.slice(start, end));
361 };
362
3630 parser.onPartEnd = function() {
3640 part.emit('end');
365 };
3660 break;
367
368 case 'base64':
3690 parser.onPartData = function(b, start, end) {
3700 part.transferBuffer += b.slice(start, end).toString('ascii');
371
372 /*
373 four bytes (chars) in base64 converts to three bytes in binary
374 encoding. So we should always work with a number of bytes that
375 can be divided by 4, it will result in a number of buytes that
376 can be divided vy 3.
377 */
3780 var offset = parseInt(part.transferBuffer.length / 4) * 4;
3790 part.emit('data', new Buffer(part.transferBuffer.substring(0, offset), 'base64'))
3800 part.transferBuffer = part.transferBuffer.substring(offset);
381 };
382
3830 parser.onPartEnd = function() {
3840 part.emit('data', new Buffer(part.transferBuffer, 'base64'))
3850 part.emit('end');
386 };
3870 break;
388
389 default:
3900 return self._error(new Error('unknown transfer-encoding'));
391 }
392
3930 self.onPart(part);
394 };
395
396
3970 parser.onEnd = function() {
3980 self.ended = true;
3990 self._maybeEnd();
400 };
401
4020 this._parser = parser;
403};
404
4051IncomingForm.prototype._fileName = function(headerValue) {
4060 var m = headerValue.match(/\bfilename="(.*?)"($|; )/i);
4070 if (!m) return;
408
4090 var filename = m[1].substr(m[1].lastIndexOf('\\') + 1);
4100 filename = filename.replace(/%22/g, '"');
4110 filename = filename.replace(/&#([\d]{4});/g, function(m, code) {
4120 return String.fromCharCode(code);
413 });
4140 return filename;
415};
416
4171IncomingForm.prototype._initUrlencoded = function() {
4180 this.type = 'urlencoded';
419
4200 var parser = new QuerystringParser(this.maxFields)
421 , self = this;
422
4230 parser.onField = function(key, val) {
4240 self.emit('field', key, val);
425 };
426
4270 parser.onEnd = function() {
4280 self.ended = true;
4290 self._maybeEnd();
430 };
431
4320 this._parser = parser;
433};
434
4351IncomingForm.prototype._initOctetStream = function() {
4360 this.type = 'octet-stream';
4370 var filename = this.headers['x-file-name'];
4380 var mime = this.headers['content-type'];
439
4400 var file = new File({
441 path: this._uploadPath(filename),
442 name: filename,
443 type: mime
444 });
445
4460 file.open();
447
4480 this.emit('fileBegin', filename, file);
449
4500 this._flushing++;
451
4520 var self = this;
453
4540 self._parser = new OctetParser();
455
456 //Keep track of writes that haven't finished so we don't emit the file before it's done being written
4570 var outstandingWrites = 0;
458
4590 self._parser.on('data', function(buffer){
4600 self.pause();
4610 outstandingWrites++;
462
4630 file.write(buffer, function() {
4640 outstandingWrites--;
4650 self.resume();
466
4670 if(self.ended){
4680 self._parser.emit('doneWritingFile');
469 }
470 });
471 });
472
4730 self._parser.on('end', function(){
4740 self._flushing--;
4750 self.ended = true;
476
4770 var done = function(){
4780 self.emit('file', 'file', file);
4790 self._maybeEnd();
480 };
481
4820 if(outstandingWrites === 0){
4830 done();
484 } else {
4850 self._parser.once('doneWritingFile', done);
486 }
487 });
488};
489
4901IncomingForm.prototype._initJSONencoded = function() {
4910 this.type = 'json';
492
4930 var parser = new JSONParser()
494 , self = this;
495
4960 if (this.bytesExpected) {
4970 parser.initWithLength(this.bytesExpected);
498 }
499
5000 parser.onField = function(key, val) {
5010 self.emit('field', key, val);
502 }
503
5040 parser.onEnd = function() {
5050 self.ended = true;
5060 self._maybeEnd();
507 };
508
5090 this._parser = parser;
510};
511
5121IncomingForm.prototype._uploadPath = function(filename) {
5130 var name = '';
5140 for (var i = 0; i < 32; i++) {
5150 name += Math.floor(Math.random() * 16).toString(16);
516 }
517
5180 if (this.keepExtensions) {
5190 var ext = path.extname(filename);
5200 ext = ext.replace(/(\.[a-z0-9]+).*/, '$1');
521
5220 name += ext;
523 }
524
5250 return path.join(this.uploadDir, name);
526};
527
5281IncomingForm.prototype._maybeEnd = function() {
5290 if (!this.ended || this._flushing || this.error) {
5300 return;
531 }
532
5330 this.emit('end');
534};
535
536

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/index.js

100%
3
3
0
LineHitsSource
11var IncomingForm = require('./incoming_form').IncomingForm;
21IncomingForm.IncomingForm = IncomingForm;
31module.exports = IncomingForm;
4

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/json_parser.js

33%
21
7
14
LineHitsSource
11if (global.GENTLY) require = GENTLY.hijack(require);
2
31var Buffer = require('buffer').Buffer
4
51function JSONParser() {
60 this.data = new Buffer('');
70 this.bytesWritten = 0;
8};
91exports.JSONParser = JSONParser;
10
111JSONParser.prototype.initWithLength = function(length) {
120 this.data = new Buffer(length);
13}
14
151JSONParser.prototype.write = function(buffer) {
160 if (this.data.length >= this.bytesWritten + buffer.length) {
170 buffer.copy(this.data, this.bytesWritten);
18 } else {
190 this.data = Buffer.concat([this.data, buffer]);
20 }
210 this.bytesWritten += buffer.length;
220 return buffer.length;
23}
24
251JSONParser.prototype.end = function() {
260 try {
270 var fields = JSON.parse(this.data.toString('utf8'))
280 for (var field in fields) {
290 this.onField(field, fields[field]);
30 }
31 } catch (e) {}
320 this.data = null;
33
340 this.onEnd();
35}

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/multipart_parser.js

5%
170
10
160
LineHitsSource
11var Buffer = require('buffer').Buffer,
2 s = 0,
3 S =
4 { PARSER_UNINITIALIZED: s++,
5 START: s++,
6 START_BOUNDARY: s++,
7 HEADER_FIELD_START: s++,
8 HEADER_FIELD: s++,
9 HEADER_VALUE_START: s++,
10 HEADER_VALUE: s++,
11 HEADER_VALUE_ALMOST_DONE: s++,
12 HEADERS_ALMOST_DONE: s++,
13 PART_DATA_START: s++,
14 PART_DATA: s++,
15 PART_END: s++,
16 END: s++
17 },
18
19 f = 1,
20 F =
21 { PART_BOUNDARY: f,
22 LAST_BOUNDARY: f *= 2
23 },
24
25 LF = 10,
26 CR = 13,
27 SPACE = 32,
28 HYPHEN = 45,
29 COLON = 58,
30 A = 97,
31 Z = 122,
32
33 lower = function(c) {
340 return c | 0x20;
35 };
36
371for (s in S) {
3813 exports[s] = S[s];
39}
40
411function MultipartParser() {
420 this.boundary = null;
430 this.boundaryChars = null;
440 this.lookbehind = null;
450 this.state = S.PARSER_UNINITIALIZED;
46
470 this.index = null;
480 this.flags = 0;
49};
501exports.MultipartParser = MultipartParser;
51
521MultipartParser.stateToString = function(stateNumber) {
530 for (var state in S) {
540 var number = S[state];
550 if (number === stateNumber) return state;
56 }
57};
58
591MultipartParser.prototype.initWithBoundary = function(str) {
600 this.boundary = new Buffer(str.length+4);
610 this.boundary.write('\r\n--', 'ascii', 0);
620 this.boundary.write(str, 'ascii', 4);
630 this.lookbehind = new Buffer(this.boundary.length+8);
640 this.state = S.START;
65
660 this.boundaryChars = {};
670 for (var i = 0; i < this.boundary.length; i++) {
680 this.boundaryChars[this.boundary[i]] = true;
69 }
70};
71
721MultipartParser.prototype.write = function(buffer) {
730 var self = this,
74 i = 0,
75 len = buffer.length,
76 prevIndex = this.index,
77 index = this.index,
78 state = this.state,
79 flags = this.flags,
80 lookbehind = this.lookbehind,
81 boundary = this.boundary,
82 boundaryChars = this.boundaryChars,
83 boundaryLength = this.boundary.length,
84 boundaryEnd = boundaryLength - 1,
85 bufferLength = buffer.length,
86 c,
87 cl,
88
89 mark = function(name) {
900 self[name+'Mark'] = i;
91 },
92 clear = function(name) {
930 delete self[name+'Mark'];
94 },
95 callback = function(name, buffer, start, end) {
960 if (start !== undefined && start === end) {
970 return;
98 }
99
1000 var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
1010 if (callbackSymbol in self) {
1020 self[callbackSymbol](buffer, start, end);
103 }
104 },
105 dataCallback = function(name, clear) {
1060 var markSymbol = name+'Mark';
1070 if (!(markSymbol in self)) {
1080 return;
109 }
110
1110 if (!clear) {
1120 callback(name, buffer, self[markSymbol], buffer.length);
1130 self[markSymbol] = 0;
114 } else {
1150 callback(name, buffer, self[markSymbol], i);
1160 delete self[markSymbol];
117 }
118 };
119
1200 for (i = 0; i < len; i++) {
1210 c = buffer[i];
1220 switch (state) {
123 case S.PARSER_UNINITIALIZED:
1240 return i;
125 case S.START:
1260 index = 0;
1270 state = S.START_BOUNDARY;
128 case S.START_BOUNDARY:
1290 if (index == boundary.length - 2) {
1300 if (c != CR) {
1310 return i;
132 }
1330 index++;
1340 break;
1350 } else if (index - 1 == boundary.length - 2) {
1360 if (c != LF) {
1370 return i;
138 }
1390 index = 0;
1400 callback('partBegin');
1410 state = S.HEADER_FIELD_START;
1420 break;
143 }
144
1450 if (c != boundary[index+2]) {
1460 index = -2;
147 }
1480 if (c == boundary[index+2]) {
1490 index++;
150 }
1510 break;
152 case S.HEADER_FIELD_START:
1530 state = S.HEADER_FIELD;
1540 mark('headerField');
1550 index = 0;
156 case S.HEADER_FIELD:
1570 if (c == CR) {
1580 clear('headerField');
1590 state = S.HEADERS_ALMOST_DONE;
1600 break;
161 }
162
1630 index++;
1640 if (c == HYPHEN) {
1650 break;
166 }
167
1680 if (c == COLON) {
1690 if (index == 1) {
170 // empty header field
1710 return i;
172 }
1730 dataCallback('headerField', true);
1740 state = S.HEADER_VALUE_START;
1750 break;
176 }
177
1780 cl = lower(c);
1790 if (cl < A || cl > Z) {
1800 return i;
181 }
1820 break;
183 case S.HEADER_VALUE_START:
1840 if (c == SPACE) {
1850 break;
186 }
187
1880 mark('headerValue');
1890 state = S.HEADER_VALUE;
190 case S.HEADER_VALUE:
1910 if (c == CR) {
1920 dataCallback('headerValue', true);
1930 callback('headerEnd');
1940 state = S.HEADER_VALUE_ALMOST_DONE;
195 }
1960 break;
197 case S.HEADER_VALUE_ALMOST_DONE:
1980 if (c != LF) {
1990 return i;
200 }
2010 state = S.HEADER_FIELD_START;
2020 break;
203 case S.HEADERS_ALMOST_DONE:
2040 if (c != LF) {
2050 return i;
206 }
207
2080 callback('headersEnd');
2090 state = S.PART_DATA_START;
2100 break;
211 case S.PART_DATA_START:
2120 state = S.PART_DATA;
2130 mark('partData');
214 case S.PART_DATA:
2150 prevIndex = index;
216
2170 if (index == 0) {
218 // boyer-moore derrived algorithm to safely skip non-boundary data
2190 i += boundaryEnd;
2200 while (i < bufferLength && !(buffer[i] in boundaryChars)) {
2210 i += boundaryLength;
222 }
2230 i -= boundaryEnd;
2240 c = buffer[i];
225 }
226
2270 if (index < boundary.length) {
2280 if (boundary[index] == c) {
2290 if (index == 0) {
2300 dataCallback('partData', true);
231 }
2320 index++;
233 } else {
2340 index = 0;
235 }
2360 } else if (index == boundary.length) {
2370 index++;
2380 if (c == CR) {
239 // CR = part boundary
2400 flags |= F.PART_BOUNDARY;
2410 } else if (c == HYPHEN) {
242 // HYPHEN = end boundary
2430 flags |= F.LAST_BOUNDARY;
244 } else {
2450 index = 0;
246 }
2470 } else if (index - 1 == boundary.length) {
2480 if (flags & F.PART_BOUNDARY) {
2490 index = 0;
2500 if (c == LF) {
251 // unset the PART_BOUNDARY flag
2520 flags &= ~F.PART_BOUNDARY;
2530 callback('partEnd');
2540 callback('partBegin');
2550 state = S.HEADER_FIELD_START;
2560 break;
257 }
2580 } else if (flags & F.LAST_BOUNDARY) {
2590 if (c == HYPHEN) {
2600 callback('partEnd');
2610 callback('end');
2620 state = S.END;
263 } else {
2640 index = 0;
265 }
266 } else {
2670 index = 0;
268 }
269 }
270
2710 if (index > 0) {
272 // when matching a possible boundary, keep a lookbehind reference
273 // in case it turns out to be a false lead
2740 lookbehind[index-1] = c;
2750 } else if (prevIndex > 0) {
276 // if our boundary turned out to be rubbish, the captured lookbehind
277 // belongs to partData
2780 callback('partData', lookbehind, 0, prevIndex);
2790 prevIndex = 0;
2800 mark('partData');
281
282 // reconsider the current character even so it interrupted the sequence
283 // it could be the beginning of a new sequence
2840 i--;
285 }
286
2870 break;
288 case S.END:
2890 break;
290 default:
2910 return i;
292 }
293 }
294
2950 dataCallback('headerField');
2960 dataCallback('headerValue');
2970 dataCallback('partData');
298
2990 this.index = index;
3000 this.state = state;
3010 this.flags = flags;
302
3030 return len;
304};
305
3061MultipartParser.prototype.end = function() {
3070 var callback = function(self, name) {
3080 var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
3090 if (callbackSymbol in self) {
3100 self[callbackSymbol]();
311 }
312 };
3130 if ((this.state == S.HEADER_FIELD_START && this.index == 0) ||
314 (this.state == S.PART_DATA && this.index == this.boundary.length)) {
3150 callback(this, 'partEnd');
3160 callback(this, 'end');
3170 } else if (this.state != S.END) {
3180 return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain());
319 }
320};
321
3221MultipartParser.prototype.explain = function() {
3230 return 'state = ' + MultipartParser.stateToString(this.state);
324};
325

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/octet_parser.js

54%
11
6
5
LineHitsSource
11var EventEmitter = require('events').EventEmitter
2 , util = require('util');
3
41function OctetParser(options){
50 if(!(this instanceof OctetParser)) return new OctetParser(options);
60 EventEmitter.call(this);
7}
8
91util.inherits(OctetParser, EventEmitter);
10
111exports.OctetParser = OctetParser;
12
131OctetParser.prototype.write = function(buffer) {
140 this.emit('data', buffer);
150 return buffer.length;
16};
17
181OctetParser.prototype.end = function() {
190 this.emit('end');
20};
21

/Users/lcalvy/Documents/Boulot/Sources/tp-workflow-production/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/querystring_parser.js

40%
15
6
9
LineHitsSource
11if (global.GENTLY) require = GENTLY.hijack(require);
2
3// This is a buffering parser, not quite as nice as the multipart one.
4// If I find time I'll rewrite this to be fully streaming as well
51var querystring = require('querystring');
6
71function QuerystringParser(maxKeys) {
80 this.maxKeys = maxKeys;
90 this.buffer = '';
10};
111exports.QuerystringParser = QuerystringParser;
12
131QuerystringParser.prototype.write = function(buffer) {
140 this.buffer += buffer.toString('ascii');
150 return buffer.length;
16};
17
181QuerystringParser.prototype.end = function() {
190 var fields = querystring.parse(this.buffer, '&', '=', { maxKeys: this.maxKeys });
200 for (var field in fields) {
210 this.onField(field, fields[field]);
22 }
230 this.buffer = '';
24
250 this.onEnd();
26};
27
28